From 6616b5282322bc6d6770ebf3e444071a087501e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 18 Dec 2024 12:16:03 +0300 Subject: [PATCH 001/300] K8SPG-647: Fix major-upgrade test --- e2e-tests/tests/major-upgrade/10-assert.yaml | 17 ++++++ e2e-tests/tests/major-upgrade/11-assert.yaml | 21 -------- .../tests/major-upgrade/11-change-repo.yaml | 12 ----- e2e-tests/tests/major-upgrade/11-wait.yaml | 16 ++++++ e2e-tests/tests/major-upgrade/12-assert.yaml | 4 +- .../tests/major-upgrade/12-run-backup.yaml | 2 +- .../{13-assert.yaml => 18-assert.yaml} | 2 +- ...3-run-restore.yaml => 18-run-restore.yaml} | 2 +- .../{14-assert.yaml => 19-assert.yaml} | 2 +- ...primary.yaml => 19-read-from-primary.yaml} | 2 +- e2e-tests/tests/major-upgrade/20-assert.yaml | 2 +- e2e-tests/tests/major-upgrade/21-assert.yaml | 21 -------- .../tests/major-upgrade/21-change-repo.yaml | 12 ----- e2e-tests/tests/major-upgrade/21-wait.yaml | 16 ++++++ e2e-tests/tests/major-upgrade/22-assert.yaml | 4 +- .../tests/major-upgrade/22-run-backup.yaml | 2 +- .../{23-assert.yaml => 28-assert.yaml} | 2 +- ...3-run-restore.yaml => 28-run-restore.yaml} | 2 +- .../{34-assert.yaml => 29-assert.yaml} | 2 +- ...primary.yaml => 29-read-from-primary.yaml} | 2 +- e2e-tests/tests/major-upgrade/31-assert.yaml | 21 -------- .../tests/major-upgrade/31-change-repo.yaml | 12 ----- e2e-tests/tests/major-upgrade/31-wait.yaml | 16 ++++++ e2e-tests/tests/major-upgrade/32-assert.yaml | 4 +- .../tests/major-upgrade/32-run-backup.yaml | 2 +- .../{33-assert.yaml => 38-assert.yaml} | 2 +- ...3-run-restore.yaml => 38-run-restore.yaml} | 2 +- .../{24-assert.yaml => 39-assert.yaml} | 2 +- ...primary.yaml => 39-read-from-primary.yaml} | 2 +- e2e-tests/tests/major-upgrade/41-assert.yaml | 21 -------- .../tests/major-upgrade/41-change-repo.yaml | 12 ----- e2e-tests/tests/major-upgrade/41-wait.yaml | 16 ++++++ e2e-tests/tests/major-upgrade/46-assert.yaml | 21 -------- e2e-tests/tests/major-upgrade/48-assert.yaml | 54 ++++++++++++++++--- .../tests/major-upgrade/48-run-restore.yaml | 2 +- .../{44-assert.yaml => 49-assert.yaml} | 2 +- .../major-upgrade/49-read-from-primary.yaml | 2 +- .../{45-16-to-17.yaml => 50-16-to-17.yaml} | 0 .../{45-assert.yaml => 50-assert.yaml} | 0 e2e-tests/tests/major-upgrade/51-wait.yaml | 16 ++++++ .../{47-assert.yaml => 52-assert.yaml} | 0 ...{47-run-backup.yaml => 52-run-backup.yaml} | 0 .../{43-assert.yaml => 58-assert.yaml} | 2 +- ...3-run-restore.yaml => 58-run-restore.yaml} | 2 +- e2e-tests/tests/major-upgrade/59-assert.yaml | 10 ++++ ...primary.yaml => 59-read-from-primary.yaml} | 2 +- 46 files changed, 183 insertions(+), 187 deletions(-) delete mode 100644 e2e-tests/tests/major-upgrade/11-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/11-change-repo.yaml create mode 100644 e2e-tests/tests/major-upgrade/11-wait.yaml rename e2e-tests/tests/major-upgrade/{13-assert.yaml => 18-assert.yaml} (98%) rename e2e-tests/tests/major-upgrade/{13-run-restore.yaml => 18-run-restore.yaml} (87%) rename e2e-tests/tests/major-upgrade/{14-assert.yaml => 19-assert.yaml} (81%) rename e2e-tests/tests/major-upgrade/{14-read-from-primary.yaml => 19-read-from-primary.yaml} (85%) delete mode 100644 e2e-tests/tests/major-upgrade/21-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/21-change-repo.yaml create mode 100644 e2e-tests/tests/major-upgrade/21-wait.yaml rename e2e-tests/tests/major-upgrade/{23-assert.yaml => 28-assert.yaml} (98%) rename e2e-tests/tests/major-upgrade/{23-run-restore.yaml => 28-run-restore.yaml} (87%) rename e2e-tests/tests/major-upgrade/{34-assert.yaml => 29-assert.yaml} (81%) rename e2e-tests/tests/major-upgrade/{34-read-from-primary.yaml => 29-read-from-primary.yaml} (76%) delete mode 100644 e2e-tests/tests/major-upgrade/31-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/31-change-repo.yaml create mode 100644 e2e-tests/tests/major-upgrade/31-wait.yaml rename e2e-tests/tests/major-upgrade/{33-assert.yaml => 38-assert.yaml} (98%) rename e2e-tests/tests/major-upgrade/{33-run-restore.yaml => 38-run-restore.yaml} (87%) rename e2e-tests/tests/major-upgrade/{24-assert.yaml => 39-assert.yaml} (81%) rename e2e-tests/tests/major-upgrade/{44-read-from-primary.yaml => 39-read-from-primary.yaml} (76%) delete mode 100644 e2e-tests/tests/major-upgrade/41-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/41-change-repo.yaml create mode 100644 e2e-tests/tests/major-upgrade/41-wait.yaml delete mode 100644 e2e-tests/tests/major-upgrade/46-assert.yaml rename e2e-tests/tests/major-upgrade/{44-assert.yaml => 49-assert.yaml} (81%) rename e2e-tests/tests/major-upgrade/{45-16-to-17.yaml => 50-16-to-17.yaml} (100%) rename e2e-tests/tests/major-upgrade/{45-assert.yaml => 50-assert.yaml} (100%) create mode 100644 e2e-tests/tests/major-upgrade/51-wait.yaml rename e2e-tests/tests/major-upgrade/{47-assert.yaml => 52-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{47-run-backup.yaml => 52-run-backup.yaml} (100%) rename e2e-tests/tests/major-upgrade/{43-assert.yaml => 58-assert.yaml} (97%) rename e2e-tests/tests/major-upgrade/{43-run-restore.yaml => 58-run-restore.yaml} (79%) create mode 100644 e2e-tests/tests/major-upgrade/59-assert.yaml rename e2e-tests/tests/major-upgrade/{24-read-from-primary.yaml => 59-read-from-primary.yaml} (76%) diff --git a/e2e-tests/tests/major-upgrade/10-assert.yaml b/e2e-tests/tests/major-upgrade/10-assert.yaml index ae8dcb18f8..3aa5127953 100644 --- a/e2e-tests/tests/major-upgrade/10-assert.yaml +++ b/e2e-tests/tests/major-upgrade/10-assert.yaml @@ -5,6 +5,23 @@ commands: - script: |- kubectl -n ${NAMESPACE} get pg,pod,job sleep 5 + + primary=$(kubectl -n ${NAMESPACE} get pod -l postgres-operator.crunchydata.com/role=master --no-headers -o jsonpath={.items[].metadata.name} || true) + if [ -z ${primary} ]; then + echo "Waiting for pods" + exit 0 + fi + + phase=$(kubectl -n ${NAMESPACE} get pod/${primary} -o jsonpath={".status.phase"}) + if [[ "${phase}" != "Running" ]]; then + echo "Waiting for ${primary} to start running" + exit 0 + fi + + kubectl -n ${NAMESPACE} exec -it ${primary} -- patronictl list + kubectl -n ${NAMESPACE} exec -it ${primary} -- patronictl history + + sleep 10 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster diff --git a/e2e-tests/tests/major-upgrade/11-assert.yaml b/e2e-tests/tests/major-upgrade/11-assert.yaml deleted file mode 100644 index 47ccba03b5..0000000000 --- a/e2e-tests/tests/major-upgrade/11-assert.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo2 - replicaCreateBackupComplete: true - stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/11-change-repo.yaml b/e2e-tests/tests/major-upgrade/11-change-repo.yaml deleted file mode 100644 index 22094b19f4..0000000000 --- a/e2e-tests/tests/major-upgrade/11-change-repo.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - kubectl patch \ - -n $NAMESPACE \ - perconapgcluster major-upgrade \ - --type='json' \ - -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo2"}]' diff --git a/e2e-tests/tests/major-upgrade/11-wait.yaml b/e2e-tests/tests/major-upgrade/11-wait.yaml new file mode 100644 index 0000000000..ddcfd43c98 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/11-wait.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + + sleep 30 + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + echo "Checking the status of ${pod}:" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + done diff --git a/e2e-tests/tests/major-upgrade/12-assert.yaml b/e2e-tests/tests/major-upgrade/12-assert.yaml index d1790eabf5..525d522912 100644 --- a/e2e-tests/tests/major-upgrade/12-assert.yaml +++ b/e2e-tests/tests/major-upgrade/12-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-12-to-13 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo2 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -24,7 +24,7 @@ metadata: name: backup-after-12-to-13 spec: pgCluster: major-upgrade - repoName: repo2 + repoName: repo1 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/12-run-backup.yaml b/e2e-tests/tests/major-upgrade/12-run-backup.yaml index 601008d4ca..0cfac94a95 100644 --- a/e2e-tests/tests/major-upgrade/12-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade/12-run-backup.yaml @@ -4,6 +4,6 @@ metadata: name: backup-after-12-to-13 spec: pgCluster: major-upgrade - repoName: repo2 + repoName: repo1 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/13-assert.yaml b/e2e-tests/tests/major-upgrade/18-assert.yaml similarity index 98% rename from e2e-tests/tests/major-upgrade/13-assert.yaml rename to e2e-tests/tests/major-upgrade/18-assert.yaml index 2d05bb7d88..9e9bbf89ce 100644 --- a/e2e-tests/tests/major-upgrade/13-assert.yaml +++ b/e2e-tests/tests/major-upgrade/18-assert.yaml @@ -30,7 +30,7 @@ metadata: name: restore-after-12-to-13 spec: pgCluster: major-upgrade - repoName: repo2 + repoName: repo1 status: state: Succeeded --- diff --git a/e2e-tests/tests/major-upgrade/13-run-restore.yaml b/e2e-tests/tests/major-upgrade/18-run-restore.yaml similarity index 87% rename from e2e-tests/tests/major-upgrade/13-run-restore.yaml rename to e2e-tests/tests/major-upgrade/18-run-restore.yaml index bba96fe985..6350f5d6f1 100644 --- a/e2e-tests/tests/major-upgrade/13-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/18-run-restore.yaml @@ -4,4 +4,4 @@ metadata: name: restore-after-12-to-13 spec: pgCluster: major-upgrade - repoName: repo2 + repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/14-assert.yaml b/e2e-tests/tests/major-upgrade/19-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/14-assert.yaml rename to e2e-tests/tests/major-upgrade/19-assert.yaml index 7c65443fbe..381403d405 100644 --- a/e2e-tests/tests/major-upgrade/14-assert.yaml +++ b/e2e-tests/tests/major-upgrade/19-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 05-read-from-primary + name: 19-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/14-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml similarity index 85% rename from e2e-tests/tests/major-upgrade/14-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/19-read-from-primary.yaml index ac80bb337c..f835a311f5 100644 --- a/e2e-tests/tests/major-upgrade/14-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 05-read-from-primary --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 19-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/20-assert.yaml b/e2e-tests/tests/major-upgrade/20-assert.yaml index c506a745f5..23d3a30f61 100644 --- a/e2e-tests/tests/major-upgrade/20-assert.yaml +++ b/e2e-tests/tests/major-upgrade/20-assert.yaml @@ -32,7 +32,7 @@ metadata: postgres-operator.crunchydata.com/cluster: major-upgrade postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo2 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/21-assert.yaml b/e2e-tests/tests/major-upgrade/21-assert.yaml deleted file mode 100644 index 301240b0f5..0000000000 --- a/e2e-tests/tests/major-upgrade/21-assert.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo3 - replicaCreateBackupComplete: true - stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/21-change-repo.yaml b/e2e-tests/tests/major-upgrade/21-change-repo.yaml deleted file mode 100644 index 57f9edc8a4..0000000000 --- a/e2e-tests/tests/major-upgrade/21-change-repo.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - kubectl patch \ - -n $NAMESPACE \ - perconapgcluster major-upgrade \ - --type='json' \ - -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo3"}]' diff --git a/e2e-tests/tests/major-upgrade/21-wait.yaml b/e2e-tests/tests/major-upgrade/21-wait.yaml new file mode 100644 index 0000000000..ddcfd43c98 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/21-wait.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + + sleep 30 + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + echo "Checking the status of ${pod}:" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + done diff --git a/e2e-tests/tests/major-upgrade/22-assert.yaml b/e2e-tests/tests/major-upgrade/22-assert.yaml index 7a2f6c1c0f..788d3de044 100644 --- a/e2e-tests/tests/major-upgrade/22-assert.yaml +++ b/e2e-tests/tests/major-upgrade/22-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-13-to-14 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo3 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -24,7 +24,7 @@ metadata: name: backup-after-13-to-14 spec: pgCluster: major-upgrade - repoName: repo3 + repoName: repo1 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/22-run-backup.yaml b/e2e-tests/tests/major-upgrade/22-run-backup.yaml index a7a1050c53..7f60f47386 100644 --- a/e2e-tests/tests/major-upgrade/22-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade/22-run-backup.yaml @@ -4,6 +4,6 @@ metadata: name: backup-after-13-to-14 spec: pgCluster: major-upgrade - repoName: repo3 + repoName: repo1 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/23-assert.yaml b/e2e-tests/tests/major-upgrade/28-assert.yaml similarity index 98% rename from e2e-tests/tests/major-upgrade/23-assert.yaml rename to e2e-tests/tests/major-upgrade/28-assert.yaml index 75b542e689..0368526518 100644 --- a/e2e-tests/tests/major-upgrade/23-assert.yaml +++ b/e2e-tests/tests/major-upgrade/28-assert.yaml @@ -30,7 +30,7 @@ metadata: name: restore-after-13-to-14 spec: pgCluster: major-upgrade - repoName: repo3 + repoName: repo1 status: state: Succeeded --- diff --git a/e2e-tests/tests/major-upgrade/23-run-restore.yaml b/e2e-tests/tests/major-upgrade/28-run-restore.yaml similarity index 87% rename from e2e-tests/tests/major-upgrade/23-run-restore.yaml rename to e2e-tests/tests/major-upgrade/28-run-restore.yaml index 079ebf7b77..7ce7fed535 100644 --- a/e2e-tests/tests/major-upgrade/23-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/28-run-restore.yaml @@ -4,4 +4,4 @@ metadata: name: restore-after-13-to-14 spec: pgCluster: major-upgrade - repoName: repo3 + repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/34-assert.yaml b/e2e-tests/tests/major-upgrade/29-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/34-assert.yaml rename to e2e-tests/tests/major-upgrade/29-assert.yaml index 7321c61abe..c73c610e44 100644 --- a/e2e-tests/tests/major-upgrade/34-assert.yaml +++ b/e2e-tests/tests/major-upgrade/29-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 09-read-from-primary + name: 29-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/34-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/29-read-from-primary.yaml similarity index 76% rename from e2e-tests/tests/major-upgrade/34-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/29-read-from-primary.yaml index 12ff6f8d79..ebf6753f9b 100644 --- a/e2e-tests/tests/major-upgrade/34-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/29-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 09-read-from-primary --from-literal=data="${data}" \ No newline at end of file + kubectl create configmap -n "${NAMESPACE}" 29-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/31-assert.yaml b/e2e-tests/tests/major-upgrade/31-assert.yaml deleted file mode 100644 index 6af985e4b7..0000000000 --- a/e2e-tests/tests/major-upgrade/31-assert.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo4 - replicaCreateBackupComplete: true - stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/31-change-repo.yaml b/e2e-tests/tests/major-upgrade/31-change-repo.yaml deleted file mode 100644 index 33711377c4..0000000000 --- a/e2e-tests/tests/major-upgrade/31-change-repo.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - kubectl patch \ - -n $NAMESPACE \ - perconapgcluster major-upgrade \ - --type='json' \ - -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo4"}]' diff --git a/e2e-tests/tests/major-upgrade/31-wait.yaml b/e2e-tests/tests/major-upgrade/31-wait.yaml new file mode 100644 index 0000000000..ddcfd43c98 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/31-wait.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + + sleep 30 + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + echo "Checking the status of ${pod}:" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + done diff --git a/e2e-tests/tests/major-upgrade/32-assert.yaml b/e2e-tests/tests/major-upgrade/32-assert.yaml index 75daf8364c..14ca1327c2 100644 --- a/e2e-tests/tests/major-upgrade/32-assert.yaml +++ b/e2e-tests/tests/major-upgrade/32-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-14-to-15 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -24,7 +24,7 @@ metadata: name: backup-after-14-to-15 spec: pgCluster: major-upgrade - repoName: repo4 + repoName: repo1 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/32-run-backup.yaml b/e2e-tests/tests/major-upgrade/32-run-backup.yaml index 792209c20c..e787fedfca 100644 --- a/e2e-tests/tests/major-upgrade/32-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade/32-run-backup.yaml @@ -4,6 +4,6 @@ metadata: name: backup-after-14-to-15 spec: pgCluster: major-upgrade - repoName: repo4 + repoName: repo1 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/33-assert.yaml b/e2e-tests/tests/major-upgrade/38-assert.yaml similarity index 98% rename from e2e-tests/tests/major-upgrade/33-assert.yaml rename to e2e-tests/tests/major-upgrade/38-assert.yaml index 1d3a8a9aae..be93a3e621 100644 --- a/e2e-tests/tests/major-upgrade/33-assert.yaml +++ b/e2e-tests/tests/major-upgrade/38-assert.yaml @@ -30,7 +30,7 @@ metadata: name: restore-after-14-to-15 spec: pgCluster: major-upgrade - repoName: repo4 + repoName: repo1 status: state: Succeeded --- diff --git a/e2e-tests/tests/major-upgrade/33-run-restore.yaml b/e2e-tests/tests/major-upgrade/38-run-restore.yaml similarity index 87% rename from e2e-tests/tests/major-upgrade/33-run-restore.yaml rename to e2e-tests/tests/major-upgrade/38-run-restore.yaml index 8e7c7c6dab..24845cbb29 100644 --- a/e2e-tests/tests/major-upgrade/33-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/38-run-restore.yaml @@ -4,5 +4,5 @@ metadata: name: restore-after-14-to-15 spec: pgCluster: major-upgrade - repoName: repo4 + repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/24-assert.yaml b/e2e-tests/tests/major-upgrade/39-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/24-assert.yaml rename to e2e-tests/tests/major-upgrade/39-assert.yaml index c86dbb55fc..8ba87d3268 100644 --- a/e2e-tests/tests/major-upgrade/24-assert.yaml +++ b/e2e-tests/tests/major-upgrade/39-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 07-read-from-primary + name: 39-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/44-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/39-read-from-primary.yaml similarity index 76% rename from e2e-tests/tests/major-upgrade/44-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/39-read-from-primary.yaml index 7ecb6090a2..80a47927b8 100644 --- a/e2e-tests/tests/major-upgrade/44-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/39-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 11-read-from-primary --from-literal=data="${data}" \ No newline at end of file + kubectl create configmap -n "${NAMESPACE}" 39-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/41-assert.yaml b/e2e-tests/tests/major-upgrade/41-assert.yaml deleted file mode 100644 index 1b95780c8f..0000000000 --- a/e2e-tests/tests/major-upgrade/41-assert.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo1 - replicaCreateBackupComplete: true - stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/41-change-repo.yaml b/e2e-tests/tests/major-upgrade/41-change-repo.yaml deleted file mode 100644 index d3d277599f..0000000000 --- a/e2e-tests/tests/major-upgrade/41-change-repo.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - kubectl patch \ - -n $NAMESPACE \ - perconapgcluster major-upgrade \ - --type='json' \ - -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo1"}]' diff --git a/e2e-tests/tests/major-upgrade/41-wait.yaml b/e2e-tests/tests/major-upgrade/41-wait.yaml new file mode 100644 index 0000000000..ddcfd43c98 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/41-wait.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + + sleep 30 + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + echo "Checking the status of ${pod}:" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + done diff --git a/e2e-tests/tests/major-upgrade/46-assert.yaml b/e2e-tests/tests/major-upgrade/46-assert.yaml deleted file mode 100644 index 1b95780c8f..0000000000 --- a/e2e-tests/tests/major-upgrade/46-assert.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo1 - replicaCreateBackupComplete: true - stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/48-assert.yaml b/e2e-tests/tests/major-upgrade/48-assert.yaml index 95d57c293f..3114c23118 100644 --- a/e2e-tests/tests/major-upgrade/48-assert.yaml +++ b/e2e-tests/tests/major-upgrade/48-assert.yaml @@ -1,10 +1,52 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 30 +timeout: 720 +commands: +- script: |- + set -o errexit + + kubectl -n ${NAMESPACE} get pod + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + phase=$(kubectl -n ${NAMESPACE} get pod/${pod} -o jsonpath={".status.phase"}) + if [[ "${phase}" != "Running" ]]; then + echo "Waiting for ${pod} to start running" + continue + fi + echo "PostgreSQL logs from ${pod}:" + echo "find /pgdata/pg16/log -type f -iname 'postgresql*.log' -exec tail -n 30 {} \;" \ + | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null + done + + sleep 30 +collectors: +- type: pod + selector: "postgres-operator.crunchydata.com/data=postgres" + tail: 30 --- -kind: ConfigMap -apiVersion: v1 +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGRestore metadata: - name: 11-read-from-primary -data: - data: ' 100500' + name: restore-after-15-to-16 +spec: + pgCluster: major-upgrade + repoName: repo1 +status: + state: Succeeded +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: major-upgrade +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/major-upgrade/48-run-restore.yaml b/e2e-tests/tests/major-upgrade/48-run-restore.yaml index d496fe3126..c86adba0d1 100644 --- a/e2e-tests/tests/major-upgrade/48-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/48-run-restore.yaml @@ -1,7 +1,7 @@ apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore metadata: - name: restore-after-16-to-17 + name: restore-after-15-to-16 spec: pgCluster: major-upgrade repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/44-assert.yaml b/e2e-tests/tests/major-upgrade/49-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/44-assert.yaml rename to e2e-tests/tests/major-upgrade/49-assert.yaml index 95d57c293f..3ff925eeeb 100644 --- a/e2e-tests/tests/major-upgrade/44-assert.yaml +++ b/e2e-tests/tests/major-upgrade/49-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 11-read-from-primary + name: 49-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/49-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/49-read-from-primary.yaml index 03c7aa852b..0549c2c862 100644 --- a/e2e-tests/tests/major-upgrade/49-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/49-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 11-read-from-primary --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 49-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/45-16-to-17.yaml b/e2e-tests/tests/major-upgrade/50-16-to-17.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/45-16-to-17.yaml rename to e2e-tests/tests/major-upgrade/50-16-to-17.yaml diff --git a/e2e-tests/tests/major-upgrade/45-assert.yaml b/e2e-tests/tests/major-upgrade/50-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/45-assert.yaml rename to e2e-tests/tests/major-upgrade/50-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/51-wait.yaml b/e2e-tests/tests/major-upgrade/51-wait.yaml new file mode 100644 index 0000000000..ddcfd43c98 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/51-wait.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + + sleep 30 + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + echo "Checking the status of ${pod}:" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" + kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + done diff --git a/e2e-tests/tests/major-upgrade/47-assert.yaml b/e2e-tests/tests/major-upgrade/52-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/47-assert.yaml rename to e2e-tests/tests/major-upgrade/52-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/47-run-backup.yaml b/e2e-tests/tests/major-upgrade/52-run-backup.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/47-run-backup.yaml rename to e2e-tests/tests/major-upgrade/52-run-backup.yaml diff --git a/e2e-tests/tests/major-upgrade/43-assert.yaml b/e2e-tests/tests/major-upgrade/58-assert.yaml similarity index 97% rename from e2e-tests/tests/major-upgrade/43-assert.yaml rename to e2e-tests/tests/major-upgrade/58-assert.yaml index 3114c23118..97161e5125 100644 --- a/e2e-tests/tests/major-upgrade/43-assert.yaml +++ b/e2e-tests/tests/major-upgrade/58-assert.yaml @@ -27,7 +27,7 @@ collectors: apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore metadata: - name: restore-after-15-to-16 + name: restore-after-16-to-17 spec: pgCluster: major-upgrade repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/43-run-restore.yaml b/e2e-tests/tests/major-upgrade/58-run-restore.yaml similarity index 79% rename from e2e-tests/tests/major-upgrade/43-run-restore.yaml rename to e2e-tests/tests/major-upgrade/58-run-restore.yaml index c86adba0d1..d496fe3126 100644 --- a/e2e-tests/tests/major-upgrade/43-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/58-run-restore.yaml @@ -1,7 +1,7 @@ apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore metadata: - name: restore-after-15-to-16 + name: restore-after-16-to-17 spec: pgCluster: major-upgrade repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/59-assert.yaml b/e2e-tests/tests/major-upgrade/59-assert.yaml new file mode 100644 index 0000000000..3ff925eeeb --- /dev/null +++ b/e2e-tests/tests/major-upgrade/59-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 49-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/24-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/59-read-from-primary.yaml similarity index 76% rename from e2e-tests/tests/major-upgrade/24-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/59-read-from-primary.yaml index bfa5e93458..0549c2c862 100644 --- a/e2e-tests/tests/major-upgrade/24-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/59-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 07-read-from-primary --from-literal=data="${data}" \ No newline at end of file + kubectl create configmap -n "${NAMESPACE}" 49-read-from-primary --from-literal=data="${data}" From 739c19b643bb06c4f955f97055b8b6b891d3eaa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 18 Dec 2024 12:17:02 +0300 Subject: [PATCH 002/300] run only major-upgrade --- e2e-tests/run-pr.csv | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 8c0ba3867f..6b2bf90256 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -1,20 +1 @@ -custom-extensions -custom-tls -demand-backup -finalizers -init-deploy -monitoring -monitoring-pmm3 -one-pod -operator-self-healing -pitr -scaling -scheduled-backup -self-healing -sidecars -start-from-backup -tablespaces -telemetry-transfer -upgrade-consistency -upgrade-minor -users +major-upgrade From 5ce4d3c6436f95237d666a49ec7ed064b346a06c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Fri, 20 Dec 2024 10:01:20 +0300 Subject: [PATCH 003/300] fixes --- e2e-tests/tests/major-upgrade/01-assert.yaml | 2 +- .../tests/major-upgrade/02-write-data.yaml | 4 +-- e2e-tests/tests/major-upgrade/10-assert.yaml | 2 +- ...-wait.yaml => 11-wait-and-write-data.yaml} | 10 ++++++- .../tests/major-upgrade/18-run-restore.yaml | 29 ++++++++++++++----- e2e-tests/tests/major-upgrade/19-assert.yaml | 4 ++- ...-wait.yaml => 21-wait-and-write-data.yaml} | 12 ++++++++ e2e-tests/tests/major-upgrade/23-wait.yaml | 6 ++++ .../tests/major-upgrade/28-run-restore.yaml | 28 +++++++++++++----- e2e-tests/tests/major-upgrade/29-assert.yaml | 5 +++- e2e-tests/tests/major-upgrade/30-assert.yaml | 2 +- ...-wait.yaml => 31-wait-and-write-data.yaml} | 12 ++++++++ e2e-tests/tests/major-upgrade/33-wait.yaml | 6 ++++ .../tests/major-upgrade/38-run-restore.yaml | 27 ++++++++++++----- e2e-tests/tests/major-upgrade/39-assert.yaml | 6 +++- ...-wait.yaml => 41-wait-and-write-data.yaml} | 12 ++++++++ e2e-tests/tests/major-upgrade/43-wait.yaml | 6 ++++ .../tests/major-upgrade/48-run-restore.yaml | 27 ++++++++++++----- e2e-tests/tests/major-upgrade/49-assert.yaml | 7 ++++- .../tests/scheduled-backup/07-add-sleep.yaml | 8 ++++- 20 files changed, 176 insertions(+), 39 deletions(-) rename e2e-tests/tests/major-upgrade/{11-wait.yaml => 11-wait-and-write-data.yaml} (63%) rename e2e-tests/tests/major-upgrade/{41-wait.yaml => 21-wait-and-write-data.yaml} (55%) create mode 100644 e2e-tests/tests/major-upgrade/23-wait.yaml rename e2e-tests/tests/major-upgrade/{21-wait.yaml => 31-wait-and-write-data.yaml} (57%) create mode 100644 e2e-tests/tests/major-upgrade/33-wait.yaml rename e2e-tests/tests/major-upgrade/{31-wait.yaml => 41-wait-and-write-data.yaml} (57%) create mode 100644 e2e-tests/tests/major-upgrade/43-wait.yaml diff --git a/e2e-tests/tests/major-upgrade/01-assert.yaml b/e2e-tests/tests/major-upgrade/01-assert.yaml index 8fee6151e6..95aee49860 100644 --- a/e2e-tests/tests/major-upgrade/01-assert.yaml +++ b/e2e-tests/tests/major-upgrade/01-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 120 +timeout: 240 --- kind: StatefulSet apiVersion: apps/v1 diff --git a/e2e-tests/tests/major-upgrade/02-write-data.yaml b/e2e-tests/tests/major-upgrade/02-write-data.yaml index da5b97f2a7..33f2b6b270 100644 --- a/e2e-tests/tests/major-upgrade/02-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/02-write-data.yaml @@ -10,11 +10,11 @@ commands: run_psql_local \ 'CREATE DATABASE myapp; \c myapp \\\ CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY);' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - + run_psql_local \ '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" run_psql_local \ '\c postgres \\\ CREATE EXTENSION pg_cron' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" \ No newline at end of file + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/10-assert.yaml b/e2e-tests/tests/major-upgrade/10-assert.yaml index 3aa5127953..88d1233564 100644 --- a/e2e-tests/tests/major-upgrade/10-assert.yaml +++ b/e2e-tests/tests/major-upgrade/10-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 360 +timeout: 600 commands: - script: |- kubectl -n ${NAMESPACE} get pg,pod,job diff --git a/e2e-tests/tests/major-upgrade/11-wait.yaml b/e2e-tests/tests/major-upgrade/11-wait-and-write-data.yaml similarity index 63% rename from e2e-tests/tests/major-upgrade/11-wait.yaml rename to e2e-tests/tests/major-upgrade/11-wait-and-write-data.yaml index ddcfd43c98..1217065462 100644 --- a/e2e-tests/tests/major-upgrade/11-wait.yaml +++ b/e2e-tests/tests/major-upgrade/11-wait-and-write-data.yaml @@ -6,11 +6,19 @@ commands: set -o errexit set -o xtrace - sleep 30 + source ../../functions + + sleep 90 # wait some time for stanza to upgrade for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + kubectl -n ${NAMESPACE} exec -it ${pod} -- ls -l /pgdata/pg13_wal/ done + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100501)' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + diff --git a/e2e-tests/tests/major-upgrade/18-run-restore.yaml b/e2e-tests/tests/major-upgrade/18-run-restore.yaml index 6350f5d6f1..4843d9a078 100644 --- a/e2e-tests/tests/major-upgrade/18-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/18-run-restore.yaml @@ -1,7 +1,22 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo1 +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + + backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-12-to-13 -o jsonpath={.status.backupName}) + + cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - + apiVersion: pgv2.percona.com/v2 + kind: PerconaPGRestore + metadata: + name: restore-after-12-to-13 + spec: + pgCluster: major-upgrade + repoName: repo1 + options: + - --set=${backup_name} + EOF diff --git a/e2e-tests/tests/major-upgrade/19-assert.yaml b/e2e-tests/tests/major-upgrade/19-assert.yaml index 381403d405..fa54da2f33 100644 --- a/e2e-tests/tests/major-upgrade/19-assert.yaml +++ b/e2e-tests/tests/major-upgrade/19-assert.yaml @@ -7,4 +7,6 @@ apiVersion: v1 metadata: name: 19-read-from-primary data: - data: ' 100500' + data: |2- + 100500 + 100501 diff --git a/e2e-tests/tests/major-upgrade/41-wait.yaml b/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml similarity index 55% rename from e2e-tests/tests/major-upgrade/41-wait.yaml rename to e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml index ddcfd43c98..4a16a61946 100644 --- a/e2e-tests/tests/major-upgrade/41-wait.yaml +++ b/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml @@ -6,11 +6,23 @@ commands: set -o errexit set -o xtrace +<<<<<<< HEAD:e2e-tests/tests/major-upgrade/31-wait.yaml sleep 30 +======= + source ../../functions + + sleep 90 # wait some time for stanza to upgrade +>>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + kubectl -n ${NAMESPACE} exec -it ${pod} -- ls -l /pgdata/pg14_wal done + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100502)' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + diff --git a/e2e-tests/tests/major-upgrade/23-wait.yaml b/e2e-tests/tests/major-upgrade/23-wait.yaml new file mode 100644 index 0000000000..9e29055009 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/23-wait.yaml @@ -0,0 +1,6 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + sleep 60 diff --git a/e2e-tests/tests/major-upgrade/28-run-restore.yaml b/e2e-tests/tests/major-upgrade/28-run-restore.yaml index 7ce7fed535..3dddcb57fe 100644 --- a/e2e-tests/tests/major-upgrade/28-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/28-run-restore.yaml @@ -1,7 +1,21 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-13-to-14 -spec: - pgCluster: major-upgrade - repoName: repo1 +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + + backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-13-to-14 -o jsonpath={.status.backupName}) + + cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - + apiVersion: pgv2.percona.com/v2 + kind: PerconaPGRestore + metadata: + name: restore-after-13-to-14 + spec: + pgCluster: major-upgrade + repoName: repo1 + options: + - --set=${backup_name} + EOF diff --git a/e2e-tests/tests/major-upgrade/29-assert.yaml b/e2e-tests/tests/major-upgrade/29-assert.yaml index c73c610e44..0d6d533cf4 100644 --- a/e2e-tests/tests/major-upgrade/29-assert.yaml +++ b/e2e-tests/tests/major-upgrade/29-assert.yaml @@ -7,4 +7,7 @@ apiVersion: v1 metadata: name: 29-read-from-primary data: - data: ' 100500' + data: |2- + 100500 + 100501 + 100502 diff --git a/e2e-tests/tests/major-upgrade/30-assert.yaml b/e2e-tests/tests/major-upgrade/30-assert.yaml index b871b4faf8..11aac34933 100644 --- a/e2e-tests/tests/major-upgrade/30-assert.yaml +++ b/e2e-tests/tests/major-upgrade/30-assert.yaml @@ -32,7 +32,7 @@ metadata: postgres-operator.crunchydata.com/cluster: major-upgrade postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo3 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/21-wait.yaml b/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml similarity index 57% rename from e2e-tests/tests/major-upgrade/21-wait.yaml rename to e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml index ddcfd43c98..9615d41bb7 100644 --- a/e2e-tests/tests/major-upgrade/21-wait.yaml +++ b/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml @@ -6,11 +6,23 @@ commands: set -o errexit set -o xtrace +<<<<<<< HEAD:e2e-tests/tests/major-upgrade/11-wait.yaml sleep 30 +======= + source ../../functions + + sleep 90 +>>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + kubectl -n ${NAMESPACE} exec -it ${pod} -- ls -l /pgdata/pg15_wal done + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100503)' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + diff --git a/e2e-tests/tests/major-upgrade/33-wait.yaml b/e2e-tests/tests/major-upgrade/33-wait.yaml new file mode 100644 index 0000000000..9e29055009 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/33-wait.yaml @@ -0,0 +1,6 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + sleep 60 diff --git a/e2e-tests/tests/major-upgrade/38-run-restore.yaml b/e2e-tests/tests/major-upgrade/38-run-restore.yaml index 24845cbb29..36a4317773 100644 --- a/e2e-tests/tests/major-upgrade/38-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/38-run-restore.yaml @@ -1,8 +1,21 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-14-to-15 -spec: - pgCluster: major-upgrade - repoName: repo1 +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-14-to-15 -o jsonpath={.status.backupName}) + + cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - + apiVersion: pgv2.percona.com/v2 + kind: PerconaPGRestore + metadata: + name: restore-after-14-to-15 + spec: + pgCluster: major-upgrade + repoName: repo1 + options: + - --set=${backup_name} + EOF diff --git a/e2e-tests/tests/major-upgrade/39-assert.yaml b/e2e-tests/tests/major-upgrade/39-assert.yaml index 8ba87d3268..b99c68112f 100644 --- a/e2e-tests/tests/major-upgrade/39-assert.yaml +++ b/e2e-tests/tests/major-upgrade/39-assert.yaml @@ -7,4 +7,8 @@ apiVersion: v1 metadata: name: 39-read-from-primary data: - data: ' 100500' + data: |2- + 100500 + 100501 + 100502 + 100503 diff --git a/e2e-tests/tests/major-upgrade/31-wait.yaml b/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml similarity index 57% rename from e2e-tests/tests/major-upgrade/31-wait.yaml rename to e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml index ddcfd43c98..217aaab043 100644 --- a/e2e-tests/tests/major-upgrade/31-wait.yaml +++ b/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml @@ -6,11 +6,23 @@ commands: set -o errexit set -o xtrace +<<<<<<< HEAD:e2e-tests/tests/major-upgrade/21-wait.yaml sleep 30 +======= + source ../../functions + + sleep 90 +>>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + kubectl -n ${NAMESPACE} exec -it ${pod} -- ls -l /pgdata/pg16_wal done + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100504)' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + diff --git a/e2e-tests/tests/major-upgrade/43-wait.yaml b/e2e-tests/tests/major-upgrade/43-wait.yaml new file mode 100644 index 0000000000..9e29055009 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/43-wait.yaml @@ -0,0 +1,6 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + sleep 60 diff --git a/e2e-tests/tests/major-upgrade/48-run-restore.yaml b/e2e-tests/tests/major-upgrade/48-run-restore.yaml index c86adba0d1..0e8195bf2b 100644 --- a/e2e-tests/tests/major-upgrade/48-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/48-run-restore.yaml @@ -1,8 +1,21 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-15-to-16 -spec: - pgCluster: major-upgrade - repoName: repo1 +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 600 + script: |- + set -o errexit + set -o xtrace + backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-15-to-16 -o jsonpath={.status.backupName}) + + cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - + apiVersion: pgv2.percona.com/v2 + kind: PerconaPGRestore + metadata: + name: restore-after-15-to-16 + spec: + pgCluster: major-upgrade + repoName: repo1 + options: + - --set=${backup_name} + EOF diff --git a/e2e-tests/tests/major-upgrade/49-assert.yaml b/e2e-tests/tests/major-upgrade/49-assert.yaml index 3ff925eeeb..cb611a153c 100644 --- a/e2e-tests/tests/major-upgrade/49-assert.yaml +++ b/e2e-tests/tests/major-upgrade/49-assert.yaml @@ -7,4 +7,9 @@ apiVersion: v1 metadata: name: 49-read-from-primary data: - data: ' 100500' + data: |2- + 100500 + 100501 + 100502 + 100503 + 100504 diff --git a/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml b/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml index 5fe0203828..c242d965b6 100644 --- a/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml +++ b/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml @@ -1,8 +1,14 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: +<<<<<<< HEAD:e2e-tests/tests/scheduled-backup/07-add-sleep.yaml - script: |- set -o errexit set -o xtrace - sleep 2 \ No newline at end of file + sleep 2 +======= + - timeout: 600 + script: |- + sleep 60 +>>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/13-wait.yaml From bde5dd01af87ecd1fc30a8ee0917e3cd5c8c1533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 22 Jan 2025 15:57:17 +0300 Subject: [PATCH 004/300] WIP --- .../major-upgrade/01-create-cluster.yaml | 8 +-- .../tests/major-upgrade/10-12-to-13.yaml | 24 -------- e2e-tests/tests/major-upgrade/10-assert.yaml | 59 ------------------- .../major-upgrade/11-wait-and-write-data.yaml | 24 -------- e2e-tests/tests/major-upgrade/12-assert.yaml | 31 ---------- .../tests/major-upgrade/12-run-backup.yaml | 9 --- e2e-tests/tests/major-upgrade/18-assert.yaml | 52 ---------------- .../tests/major-upgrade/18-run-restore.yaml | 22 ------- e2e-tests/tests/major-upgrade/19-assert.yaml | 12 ---- .../major-upgrade/19-read-from-primary.yaml | 12 ---- 10 files changed, 4 insertions(+), 249 deletions(-) delete mode 100644 e2e-tests/tests/major-upgrade/10-12-to-13.yaml delete mode 100644 e2e-tests/tests/major-upgrade/10-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/11-wait-and-write-data.yaml delete mode 100644 e2e-tests/tests/major-upgrade/12-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/12-run-backup.yaml delete mode 100644 e2e-tests/tests/major-upgrade/18-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/18-run-restore.yaml delete mode 100644 e2e-tests/tests/major-upgrade/19-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/19-read-from-primary.yaml diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml index 729fbcc51f..0e0fd20fc5 100644 --- a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml +++ b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml @@ -10,11 +10,11 @@ commands: get_cr \ | yq eval ' - .spec.postgresVersion = 12 | - .spec.image = "perconalab/percona-postgresql-operator:main-ppg12-postgres" | + .spec.postgresVersion = 13 | + .spec.image = "perconalab/percona-postgresql-operator:main-ppg13-postgres" | .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | - .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-ppg12-pgbouncer" | - .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg12-pgbackrest" | + .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbouncer" | + .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbackrest" | .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.1"}]' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade/10-12-to-13.yaml b/e2e-tests/tests/major-upgrade/10-12-to-13.yaml deleted file mode 100644 index 96a7fe9207..0000000000 --- a/e2e-tests/tests/major-upgrade/10-12-to-13.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - kubectl apply -n ${NAMESPACE} -f - <<-EOF - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGUpgrade - metadata: - name: 12-to-13 - spec: - postgresClusterName: major-upgrade - image: ${IMAGE_UPGRADE} - fromPostgresVersion: 12 - toPostgresVersion: 13 - toPostgresImage: $(get_container_image "postgres" 13) - toPgBouncerImage: $(get_container_image "pgbouncer" 13) - toPgBackRestImage: $(get_container_image "pgbackrest" 13) - EOF - diff --git a/e2e-tests/tests/major-upgrade/10-assert.yaml b/e2e-tests/tests/major-upgrade/10-assert.yaml deleted file mode 100644 index 88d1233564..0000000000 --- a/e2e-tests/tests/major-upgrade/10-assert.yaml +++ /dev/null @@ -1,59 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 600 -commands: -- script: |- - kubectl -n ${NAMESPACE} get pg,pod,job - sleep 5 - - primary=$(kubectl -n ${NAMESPACE} get pod -l postgres-operator.crunchydata.com/role=master --no-headers -o jsonpath={.items[].metadata.name} || true) - if [ -z ${primary} ]; then - echo "Waiting for pods" - exit 0 - fi - - phase=$(kubectl -n ${NAMESPACE} get pod/${primary} -o jsonpath={".status.phase"}) - if [[ "${phase}" != "Running" ]]; then - echo "Waiting for ${primary} to start running" - exit 0 - fi - - kubectl -n ${NAMESPACE} exec -it ${primary} -- patronictl list - kubectl -n ${NAMESPACE} exec -it ${primary} -- patronictl history - - sleep 10 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: major-upgrade -spec: - postgresVersion: 13 -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready ---- -kind: Job -apiVersion: batch/v1 -metadata: - labels: - postgres-operator.crunchydata.com/cluster: major-upgrade - postgres-operator.crunchydata.com/pgbackrest: '' - postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo1 - ownerReferences: - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGBackup - controller: true - blockOwnerDeletion: true -status: - succeeded: 1 diff --git a/e2e-tests/tests/major-upgrade/11-wait-and-write-data.yaml b/e2e-tests/tests/major-upgrade/11-wait-and-write-data.yaml deleted file mode 100644 index 1217065462..0000000000 --- a/e2e-tests/tests/major-upgrade/11-wait-and-write-data.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - sleep 90 # wait some time for stanza to upgrade - - for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do - echo "Checking the status of ${pod}:" - kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" - kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" - kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check - kubectl -n ${NAMESPACE} exec -it ${pod} -- ls -l /pgdata/pg13_wal/ - done - - run_psql_local \ - '\c myapp \\\ INSERT INTO myApp (id) VALUES (100501)' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - diff --git a/e2e-tests/tests/major-upgrade/12-assert.yaml b/e2e-tests/tests/major-upgrade/12-assert.yaml deleted file mode 100644 index 525d522912..0000000000 --- a/e2e-tests/tests/major-upgrade/12-assert.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 ---- -kind: Job -apiVersion: batch/v1 -metadata: - annotations: - postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-12-to-13 - labels: - postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo1 - ownerReferences: - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGBackup - controller: true - blockOwnerDeletion: true -status: - succeeded: 1 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGBackup -metadata: - name: backup-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --type=full -status: - state: Succeeded diff --git a/e2e-tests/tests/major-upgrade/12-run-backup.yaml b/e2e-tests/tests/major-upgrade/12-run-backup.yaml deleted file mode 100644 index 0cfac94a95..0000000000 --- a/e2e-tests/tests/major-upgrade/12-run-backup.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGBackup -metadata: - name: backup-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --type=full diff --git a/e2e-tests/tests/major-upgrade/18-assert.yaml b/e2e-tests/tests/major-upgrade/18-assert.yaml deleted file mode 100644 index 9e9bbf89ce..0000000000 --- a/e2e-tests/tests/major-upgrade/18-assert.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 720 -commands: -- script: |- - set -o errexit - - kubectl -n ${NAMESPACE} get pod - - for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do - phase=$(kubectl -n ${NAMESPACE} get pod/${pod} -o jsonpath={".status.phase"}) - if [[ "${phase}" != "Running" ]]; then - echo "Waiting for ${pod} to start running" - continue - fi - echo "PostgreSQL logs from ${pod}:" - echo "find /pgdata/pg13/log -type f -iname 'postgresql*.log' -exec tail -n 30 {} \;" \ - | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null - done - - sleep 30 -collectors: -- type: pod - selector: "postgres-operator.crunchydata.com/data=postgres" - tail: 30 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo1 -status: - state: Succeeded ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: major-upgrade -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready diff --git a/e2e-tests/tests/major-upgrade/18-run-restore.yaml b/e2e-tests/tests/major-upgrade/18-run-restore.yaml deleted file mode 100644 index 4843d9a078..0000000000 --- a/e2e-tests/tests/major-upgrade/18-run-restore.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - set -o errexit - set -o xtrace - - backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-12-to-13 -o jsonpath={.status.backupName}) - - cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGRestore - metadata: - name: restore-after-12-to-13 - spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --set=${backup_name} - EOF diff --git a/e2e-tests/tests/major-upgrade/19-assert.yaml b/e2e-tests/tests/major-upgrade/19-assert.yaml deleted file mode 100644 index fa54da2f33..0000000000 --- a/e2e-tests/tests/major-upgrade/19-assert.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 30 ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: 19-read-from-primary -data: - data: |2- - 100500 - 100501 diff --git a/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml deleted file mode 100644 index f835a311f5..0000000000 --- a/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -timeout: 30 -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - - kubectl create configmap -n "${NAMESPACE}" 19-read-from-primary --from-literal=data="${data}" From ca2ee3b7b7645d1ac65089f2e1eeb323c90dea71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Thu, 27 Mar 2025 16:36:40 +0300 Subject: [PATCH 005/300] WIP --- e2e-tests/tests/major-upgrade/01-assert.yaml | 2 +- e2e-tests/tests/major-upgrade/01-create-cluster.yaml | 4 +--- e2e-tests/tests/major-upgrade/02-write-data.yaml | 4 ---- e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml | 4 ---- e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml | 4 ---- e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml | 4 ---- e2e-tests/tests/scheduled-backup/07-add-sleep.yaml | 6 ------ 7 files changed, 2 insertions(+), 26 deletions(-) diff --git a/e2e-tests/tests/major-upgrade/01-assert.yaml b/e2e-tests/tests/major-upgrade/01-assert.yaml index 95aee49860..b580d781dc 100644 --- a/e2e-tests/tests/major-upgrade/01-assert.yaml +++ b/e2e-tests/tests/major-upgrade/01-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 240 +timeout: 300 --- kind: StatefulSet apiVersion: apps/v1 diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml index 0e0fd20fc5..9157de0d70 100644 --- a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml +++ b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml @@ -14,7 +14,5 @@ commands: .spec.image = "perconalab/percona-postgresql-operator:main-ppg13-postgres" | .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbouncer" | - .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbackrest" | - .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | - .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.1"}]' \ + .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbackrest"' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade/02-write-data.yaml b/e2e-tests/tests/major-upgrade/02-write-data.yaml index 33f2b6b270..9dab40255e 100644 --- a/e2e-tests/tests/major-upgrade/02-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/02-write-data.yaml @@ -14,7 +14,3 @@ commands: run_psql_local \ '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - - run_psql_local \ - '\c postgres \\\ CREATE EXTENSION pg_cron' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml b/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml index 4a16a61946..ea0567fa50 100644 --- a/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml @@ -6,13 +6,9 @@ commands: set -o errexit set -o xtrace -<<<<<<< HEAD:e2e-tests/tests/major-upgrade/31-wait.yaml - sleep 30 -======= source ../../functions sleep 90 # wait some time for stanza to upgrade ->>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" diff --git a/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml b/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml index 9615d41bb7..e3cbe58bce 100644 --- a/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml @@ -6,13 +6,9 @@ commands: set -o errexit set -o xtrace -<<<<<<< HEAD:e2e-tests/tests/major-upgrade/11-wait.yaml - sleep 30 -======= source ../../functions sleep 90 ->>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" diff --git a/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml b/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml index 217aaab043..bcfed0f3d3 100644 --- a/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml @@ -6,13 +6,9 @@ commands: set -o errexit set -o xtrace -<<<<<<< HEAD:e2e-tests/tests/major-upgrade/21-wait.yaml - sleep 30 -======= source ../../functions sleep 90 ->>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" diff --git a/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml b/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml index c242d965b6..e2983b9513 100644 --- a/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml +++ b/e2e-tests/tests/scheduled-backup/07-add-sleep.yaml @@ -1,14 +1,8 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep commands: -<<<<<<< HEAD:e2e-tests/tests/scheduled-backup/07-add-sleep.yaml - script: |- set -o errexit set -o xtrace sleep 2 -======= - - timeout: 600 - script: |- - sleep 60 ->>>>>>> 99139337e (fixes):e2e-tests/tests/major-upgrade/13-wait.yaml From c15dfb12bb1fff502af2ed1868480f0365fcad63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Mon, 7 Apr 2025 21:53:39 +0300 Subject: [PATCH 006/300] fix --- .../major-upgrade/01-create-cluster.yaml | 1 + .../major-upgrade/21-wait-and-write-data.yaml | 2 +- .../tests/major-upgrade/28-run-restore.yaml | 28 +++++-------------- e2e-tests/tests/major-upgrade/29-assert.yaml | 1 - .../major-upgrade/31-wait-and-write-data.yaml | 2 +- .../tests/major-upgrade/38-run-restore.yaml | 28 +++++-------------- e2e-tests/tests/major-upgrade/39-assert.yaml | 1 - .../major-upgrade/41-wait-and-write-data.yaml | 2 +- .../tests/major-upgrade/48-run-restore.yaml | 28 +++++-------------- e2e-tests/tests/major-upgrade/49-assert.yaml | 1 - ...-wait.yaml => 51-wait-and-write-data.yaml} | 10 ++++++- .../tests/major-upgrade/58-run-restore.yaml | 1 - e2e-tests/tests/major-upgrade/59-assert.yaml | 7 ++++- 13 files changed, 40 insertions(+), 72 deletions(-) rename e2e-tests/tests/major-upgrade/{51-wait.yaml => 51-wait-and-write-data.yaml} (65%) diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml index 9157de0d70..ef9f6ffa0f 100644 --- a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml +++ b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml @@ -13,6 +13,7 @@ commands: .spec.postgresVersion = 13 | .spec.image = "perconalab/percona-postgresql-operator:main-ppg13-postgres" | .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | + .spec.patroni.createReplicaMethods = ["basebackup","pgbackrest"] | .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbouncer" | .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbackrest"' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml b/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml index ea0567fa50..5310fcb884 100644 --- a/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/21-wait-and-write-data.yaml @@ -19,6 +19,6 @@ commands: done run_psql_local \ - '\c myapp \\\ INSERT INTO myApp (id) VALUES (100502)' \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100501)' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/28-run-restore.yaml b/e2e-tests/tests/major-upgrade/28-run-restore.yaml index 3dddcb57fe..7ce7fed535 100644 --- a/e2e-tests/tests/major-upgrade/28-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/28-run-restore.yaml @@ -1,21 +1,7 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - set -o errexit - set -o xtrace - - backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-13-to-14 -o jsonpath={.status.backupName}) - - cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGRestore - metadata: - name: restore-after-13-to-14 - spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --set=${backup_name} - EOF +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGRestore +metadata: + name: restore-after-13-to-14 +spec: + pgCluster: major-upgrade + repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/29-assert.yaml b/e2e-tests/tests/major-upgrade/29-assert.yaml index 0d6d533cf4..bf53e293ae 100644 --- a/e2e-tests/tests/major-upgrade/29-assert.yaml +++ b/e2e-tests/tests/major-upgrade/29-assert.yaml @@ -10,4 +10,3 @@ data: data: |2- 100500 100501 - 100502 diff --git a/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml b/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml index e3cbe58bce..0f5381c29d 100644 --- a/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/31-wait-and-write-data.yaml @@ -19,6 +19,6 @@ commands: done run_psql_local \ - '\c myapp \\\ INSERT INTO myApp (id) VALUES (100503)' \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100502)' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/38-run-restore.yaml b/e2e-tests/tests/major-upgrade/38-run-restore.yaml index 36a4317773..b809cea860 100644 --- a/e2e-tests/tests/major-upgrade/38-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/38-run-restore.yaml @@ -1,21 +1,7 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - set -o errexit - set -o xtrace - - backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-14-to-15 -o jsonpath={.status.backupName}) - - cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGRestore - metadata: - name: restore-after-14-to-15 - spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --set=${backup_name} - EOF +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGRestore +metadata: + name: restore-after-14-to-15 +spec: + pgCluster: major-upgrade + repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/39-assert.yaml b/e2e-tests/tests/major-upgrade/39-assert.yaml index b99c68112f..8bf192f7d0 100644 --- a/e2e-tests/tests/major-upgrade/39-assert.yaml +++ b/e2e-tests/tests/major-upgrade/39-assert.yaml @@ -11,4 +11,3 @@ data: 100500 100501 100502 - 100503 diff --git a/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml b/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml index bcfed0f3d3..45cbb360c8 100644 --- a/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml +++ b/e2e-tests/tests/major-upgrade/41-wait-and-write-data.yaml @@ -19,6 +19,6 @@ commands: done run_psql_local \ - '\c myapp \\\ INSERT INTO myApp (id) VALUES (100504)' \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100503)' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/48-run-restore.yaml b/e2e-tests/tests/major-upgrade/48-run-restore.yaml index 0e8195bf2b..ccaf6697b4 100644 --- a/e2e-tests/tests/major-upgrade/48-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/48-run-restore.yaml @@ -1,21 +1,7 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - set -o errexit - set -o xtrace - - backup_name=$(kubectl -n ${NAMESPACE} get pg-backup backup-after-15-to-16 -o jsonpath={.status.backupName}) - - cat <<-EOF | kubectl -n ${NAMESPACE} apply -f - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGRestore - metadata: - name: restore-after-15-to-16 - spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --set=${backup_name} - EOF +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGRestore +metadata: + name: restore-after-15-to-16 +spec: + pgCluster: major-upgrade + repoName: repo1 diff --git a/e2e-tests/tests/major-upgrade/49-assert.yaml b/e2e-tests/tests/major-upgrade/49-assert.yaml index cb611a153c..f13f428d81 100644 --- a/e2e-tests/tests/major-upgrade/49-assert.yaml +++ b/e2e-tests/tests/major-upgrade/49-assert.yaml @@ -12,4 +12,3 @@ data: 100501 100502 100503 - 100504 diff --git a/e2e-tests/tests/major-upgrade/51-wait.yaml b/e2e-tests/tests/major-upgrade/51-wait-and-write-data.yaml similarity index 65% rename from e2e-tests/tests/major-upgrade/51-wait.yaml rename to e2e-tests/tests/major-upgrade/51-wait-and-write-data.yaml index ddcfd43c98..bcfed0f3d3 100644 --- a/e2e-tests/tests/major-upgrade/51-wait.yaml +++ b/e2e-tests/tests/major-upgrade/51-wait-and-write-data.yaml @@ -6,11 +6,19 @@ commands: set -o errexit set -o xtrace - sleep 30 + source ../../functions + + sleep 90 for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do echo "Checking the status of ${pod}:" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT version()" kubectl -n ${NAMESPACE} exec -it ${pod} -- psql -c "SELECT timeline_id FROM pg_control_checkpoint()" kubectl -n ${NAMESPACE} exec -it ${pod} -- pgbackrest --stanza=db --log-level-console=detail check + kubectl -n ${NAMESPACE} exec -it ${pod} -- ls -l /pgdata/pg16_wal done + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100504)' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + diff --git a/e2e-tests/tests/major-upgrade/58-run-restore.yaml b/e2e-tests/tests/major-upgrade/58-run-restore.yaml index d496fe3126..5df2121b39 100644 --- a/e2e-tests/tests/major-upgrade/58-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/58-run-restore.yaml @@ -5,4 +5,3 @@ metadata: spec: pgCluster: major-upgrade repoName: repo1 - diff --git a/e2e-tests/tests/major-upgrade/59-assert.yaml b/e2e-tests/tests/major-upgrade/59-assert.yaml index 3ff925eeeb..cb611a153c 100644 --- a/e2e-tests/tests/major-upgrade/59-assert.yaml +++ b/e2e-tests/tests/major-upgrade/59-assert.yaml @@ -7,4 +7,9 @@ apiVersion: v1 metadata: name: 49-read-from-primary data: - data: ' 100500' + data: |2- + 100500 + 100501 + 100502 + 100503 + 100504 From 530bfa95a3a5630648a685b8cae5a96997cb1747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Tue, 8 Apr 2025 14:36:10 +0300 Subject: [PATCH 007/300] switch wal --- .../tests/major-upgrade/01-create-cluster.yaml | 1 - e2e-tests/tests/major-upgrade/23-switch-wal.yaml | 15 +++++++++++++++ e2e-tests/tests/major-upgrade/23-wait.yaml | 6 ------ e2e-tests/tests/major-upgrade/33-switch-wal.yaml | 15 +++++++++++++++ e2e-tests/tests/major-upgrade/33-wait.yaml | 6 ------ e2e-tests/tests/major-upgrade/40-assert.yaml | 2 +- e2e-tests/tests/major-upgrade/43-switch-wal.yaml | 15 +++++++++++++++ e2e-tests/tests/major-upgrade/43-wait.yaml | 6 ------ e2e-tests/tests/major-upgrade/50-assert.yaml | 2 +- e2e-tests/tests/major-upgrade/53-switch-wal.yaml | 15 +++++++++++++++ 10 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 e2e-tests/tests/major-upgrade/23-switch-wal.yaml delete mode 100644 e2e-tests/tests/major-upgrade/23-wait.yaml create mode 100644 e2e-tests/tests/major-upgrade/33-switch-wal.yaml delete mode 100644 e2e-tests/tests/major-upgrade/33-wait.yaml create mode 100644 e2e-tests/tests/major-upgrade/43-switch-wal.yaml delete mode 100644 e2e-tests/tests/major-upgrade/43-wait.yaml create mode 100644 e2e-tests/tests/major-upgrade/53-switch-wal.yaml diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml index ef9f6ffa0f..9157de0d70 100644 --- a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml +++ b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml @@ -13,7 +13,6 @@ commands: .spec.postgresVersion = 13 | .spec.image = "perconalab/percona-postgresql-operator:main-ppg13-postgres" | .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | - .spec.patroni.createReplicaMethods = ["basebackup","pgbackrest"] | .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbouncer" | .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbackrest"' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade/23-switch-wal.yaml b/e2e-tests/tests/major-upgrade/23-switch-wal.yaml new file mode 100644 index 0000000000..89fa23d91f --- /dev/null +++ b/e2e-tests/tests/major-upgrade/23-switch-wal.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 90 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'select pg_switch_wal()' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + + sleep 60 diff --git a/e2e-tests/tests/major-upgrade/23-wait.yaml b/e2e-tests/tests/major-upgrade/23-wait.yaml deleted file mode 100644 index 9e29055009..0000000000 --- a/e2e-tests/tests/major-upgrade/23-wait.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - sleep 60 diff --git a/e2e-tests/tests/major-upgrade/33-switch-wal.yaml b/e2e-tests/tests/major-upgrade/33-switch-wal.yaml new file mode 100644 index 0000000000..89fa23d91f --- /dev/null +++ b/e2e-tests/tests/major-upgrade/33-switch-wal.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 90 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'select pg_switch_wal()' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + + sleep 60 diff --git a/e2e-tests/tests/major-upgrade/33-wait.yaml b/e2e-tests/tests/major-upgrade/33-wait.yaml deleted file mode 100644 index 9e29055009..0000000000 --- a/e2e-tests/tests/major-upgrade/33-wait.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - sleep 60 diff --git a/e2e-tests/tests/major-upgrade/40-assert.yaml b/e2e-tests/tests/major-upgrade/40-assert.yaml index de3a338c83..317c83bb40 100644 --- a/e2e-tests/tests/major-upgrade/40-assert.yaml +++ b/e2e-tests/tests/major-upgrade/40-assert.yaml @@ -32,7 +32,7 @@ metadata: postgres-operator.crunchydata.com/cluster: major-upgrade postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/43-switch-wal.yaml b/e2e-tests/tests/major-upgrade/43-switch-wal.yaml new file mode 100644 index 0000000000..89fa23d91f --- /dev/null +++ b/e2e-tests/tests/major-upgrade/43-switch-wal.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 90 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'select pg_switch_wal()' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + + sleep 60 diff --git a/e2e-tests/tests/major-upgrade/43-wait.yaml b/e2e-tests/tests/major-upgrade/43-wait.yaml deleted file mode 100644 index 9e29055009..0000000000 --- a/e2e-tests/tests/major-upgrade/43-wait.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 600 - script: |- - sleep 60 diff --git a/e2e-tests/tests/major-upgrade/50-assert.yaml b/e2e-tests/tests/major-upgrade/50-assert.yaml index e52b25e2cb..14332948f5 100644 --- a/e2e-tests/tests/major-upgrade/50-assert.yaml +++ b/e2e-tests/tests/major-upgrade/50-assert.yaml @@ -32,7 +32,7 @@ metadata: postgres-operator.crunchydata.com/cluster: major-upgrade postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/53-switch-wal.yaml b/e2e-tests/tests/major-upgrade/53-switch-wal.yaml new file mode 100644 index 0000000000..89fa23d91f --- /dev/null +++ b/e2e-tests/tests/major-upgrade/53-switch-wal.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 90 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'select pg_switch_wal()' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + + sleep 60 From e811f7cb6336fcfb5212348edcf05b88ac477982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 9 Apr 2025 09:54:27 +0300 Subject: [PATCH 008/300] checkpoint --- e2e-tests/tests/major-upgrade/01-create-cluster.yaml | 1 + e2e-tests/tests/major-upgrade/23-switch-wal.yaml | 3 +++ e2e-tests/tests/major-upgrade/33-switch-wal.yaml | 3 +++ e2e-tests/tests/major-upgrade/43-switch-wal.yaml | 3 +++ e2e-tests/tests/major-upgrade/53-switch-wal.yaml | 3 +++ 5 files changed, 13 insertions(+) diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml index 9157de0d70..ef9f6ffa0f 100644 --- a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml +++ b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml @@ -13,6 +13,7 @@ commands: .spec.postgresVersion = 13 | .spec.image = "perconalab/percona-postgresql-operator:main-ppg13-postgres" | .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | + .spec.patroni.createReplicaMethods = ["basebackup","pgbackrest"] | .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbouncer" | .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg13-pgbackrest"' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade/23-switch-wal.yaml b/e2e-tests/tests/major-upgrade/23-switch-wal.yaml index 89fa23d91f..23c0729adb 100644 --- a/e2e-tests/tests/major-upgrade/23-switch-wal.yaml +++ b/e2e-tests/tests/major-upgrade/23-switch-wal.yaml @@ -8,6 +8,9 @@ commands: source ../../functions + run_psql_local \ + 'checkpoint' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" run_psql_local \ 'select pg_switch_wal()' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/33-switch-wal.yaml b/e2e-tests/tests/major-upgrade/33-switch-wal.yaml index 89fa23d91f..23c0729adb 100644 --- a/e2e-tests/tests/major-upgrade/33-switch-wal.yaml +++ b/e2e-tests/tests/major-upgrade/33-switch-wal.yaml @@ -8,6 +8,9 @@ commands: source ../../functions + run_psql_local \ + 'checkpoint' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" run_psql_local \ 'select pg_switch_wal()' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/43-switch-wal.yaml b/e2e-tests/tests/major-upgrade/43-switch-wal.yaml index 89fa23d91f..23c0729adb 100644 --- a/e2e-tests/tests/major-upgrade/43-switch-wal.yaml +++ b/e2e-tests/tests/major-upgrade/43-switch-wal.yaml @@ -8,6 +8,9 @@ commands: source ../../functions + run_psql_local \ + 'checkpoint' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" run_psql_local \ 'select pg_switch_wal()' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/53-switch-wal.yaml b/e2e-tests/tests/major-upgrade/53-switch-wal.yaml index 89fa23d91f..23c0729adb 100644 --- a/e2e-tests/tests/major-upgrade/53-switch-wal.yaml +++ b/e2e-tests/tests/major-upgrade/53-switch-wal.yaml @@ -8,6 +8,9 @@ commands: source ../../functions + run_psql_local \ + 'checkpoint' \ + "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" run_psql_local \ 'select pg_switch_wal()' \ "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" From eb5da3b3ba972b5d4d6c6c363b40e3883c76d793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Thu, 10 Apr 2025 19:57:47 +0300 Subject: [PATCH 009/300] WIP --- e2e-tests/tests/major-upgrade/20-assert.yaml | 13 +++++++++++++ e2e-tests/tests/major-upgrade/28-assert.yaml | 10 +++++++++- e2e-tests/tests/major-upgrade/28-run-restore.yaml | 2 ++ e2e-tests/tests/major-upgrade/30-assert.yaml | 7 +++++++ e2e-tests/tests/major-upgrade/38-assert.yaml | 5 ++++- e2e-tests/tests/major-upgrade/38-run-restore.yaml | 2 ++ e2e-tests/tests/major-upgrade/40-assert.yaml | 7 +++++++ e2e-tests/tests/major-upgrade/48-assert.yaml | 5 ++++- e2e-tests/tests/major-upgrade/48-run-restore.yaml | 2 ++ e2e-tests/tests/major-upgrade/50-assert.yaml | 7 +++++++ e2e-tests/tests/major-upgrade/58-assert.yaml | 5 ++++- e2e-tests/tests/major-upgrade/58-run-restore.yaml | 2 ++ .../tests/major-upgrade/59-read-from-primary.yaml | 2 +- 13 files changed, 64 insertions(+), 5 deletions(-) diff --git a/e2e-tests/tests/major-upgrade/20-assert.yaml b/e2e-tests/tests/major-upgrade/20-assert.yaml index 23d3a30f61..2cbe8bad8d 100644 --- a/e2e-tests/tests/major-upgrade/20-assert.yaml +++ b/e2e-tests/tests/major-upgrade/20-assert.yaml @@ -4,7 +4,20 @@ timeout: 360 commands: - script: |- kubectl -n ${NAMESPACE} get pg,pod,job + # + # for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/pgupgrade=13-to-14 | awk '{print $1}'); do + # echo "${pod} logs:" + # kubectl -n ${NAMESPACE} logs ${pod} + # done + # sleep 5 +collectors: +- type: pod + selector: "postgres-operator.crunchydata.com/data=postgres" + tail: 30 +- type: pod + selector: "postgres-operator.crunchydata.com/pgupgrade=13-to-14" + tail: 200 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster diff --git a/e2e-tests/tests/major-upgrade/28-assert.yaml b/e2e-tests/tests/major-upgrade/28-assert.yaml index 0368526518..ad1b782f7d 100644 --- a/e2e-tests/tests/major-upgrade/28-assert.yaml +++ b/e2e-tests/tests/major-upgrade/28-assert.yaml @@ -7,6 +7,11 @@ commands: kubectl -n ${NAMESPACE} get pod + # for pod in $(kubectl -n ${NAMESPACE} get pod -l job-name=major-upgrade-pgbackrest-restore | awk '{print $1}'); do + # echo "${pod} logs:" + # kubectl -n ${NAMESPACE} logs ${pod} + # done + # for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do phase=$(kubectl -n ${NAMESPACE} get pod/${pod} -o jsonpath={".status.phase"}) if [[ "${phase}" != "Running" ]]; then @@ -18,11 +23,14 @@ commands: | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null done - sleep 30 + sleep 15 collectors: - type: pod selector: "postgres-operator.crunchydata.com/data=postgres" tail: 30 +- type: pod + selector: "job-name=major-upgrade-pgbackrest-restore" + tail: 300 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore diff --git a/e2e-tests/tests/major-upgrade/28-run-restore.yaml b/e2e-tests/tests/major-upgrade/28-run-restore.yaml index 7ce7fed535..5da4967f36 100644 --- a/e2e-tests/tests/major-upgrade/28-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/28-run-restore.yaml @@ -5,3 +5,5 @@ metadata: spec: pgCluster: major-upgrade repoName: repo1 + options: + - --log-level-console=debug diff --git a/e2e-tests/tests/major-upgrade/30-assert.yaml b/e2e-tests/tests/major-upgrade/30-assert.yaml index 11aac34933..edf3605d1b 100644 --- a/e2e-tests/tests/major-upgrade/30-assert.yaml +++ b/e2e-tests/tests/major-upgrade/30-assert.yaml @@ -5,6 +5,13 @@ commands: - script: |- kubectl -n ${NAMESPACE} get pg,pod,job sleep 5 +collectors: +- type: pod + selector: "postgres-operator.crunchydata.com/data=postgres" + tail: 30 +- type: pod + selector: "postgres-operator.crunchydata.com/pgupgrade=13-to-14" + tail: 200 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster diff --git a/e2e-tests/tests/major-upgrade/38-assert.yaml b/e2e-tests/tests/major-upgrade/38-assert.yaml index be93a3e621..965f474253 100644 --- a/e2e-tests/tests/major-upgrade/38-assert.yaml +++ b/e2e-tests/tests/major-upgrade/38-assert.yaml @@ -18,11 +18,14 @@ commands: | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null done - sleep 30 + sleep 15 collectors: - type: pod selector: "postgres-operator.crunchydata.com/data=postgres" tail: 30 +- type: pod + selector: "job-name=major-upgrade-pgbackrest-restore" + tail: 300 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore diff --git a/e2e-tests/tests/major-upgrade/38-run-restore.yaml b/e2e-tests/tests/major-upgrade/38-run-restore.yaml index b809cea860..8bf3986aab 100644 --- a/e2e-tests/tests/major-upgrade/38-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/38-run-restore.yaml @@ -5,3 +5,5 @@ metadata: spec: pgCluster: major-upgrade repoName: repo1 + options: + - --log-level-console=debug diff --git a/e2e-tests/tests/major-upgrade/40-assert.yaml b/e2e-tests/tests/major-upgrade/40-assert.yaml index 317c83bb40..45a1e643b9 100644 --- a/e2e-tests/tests/major-upgrade/40-assert.yaml +++ b/e2e-tests/tests/major-upgrade/40-assert.yaml @@ -5,6 +5,13 @@ commands: - script: |- kubectl -n ${NAMESPACE} get pg,pod,job sleep 5 +collectors: +- type: pod + selector: "postgres-operator.crunchydata.com/data=postgres" + tail: 30 +- type: pod + selector: "postgres-operator.crunchydata.com/pgupgrade=13-to-14" + tail: 200 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster diff --git a/e2e-tests/tests/major-upgrade/48-assert.yaml b/e2e-tests/tests/major-upgrade/48-assert.yaml index 3114c23118..a870ac130d 100644 --- a/e2e-tests/tests/major-upgrade/48-assert.yaml +++ b/e2e-tests/tests/major-upgrade/48-assert.yaml @@ -18,11 +18,14 @@ commands: | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null done - sleep 30 + sleep 15 collectors: - type: pod selector: "postgres-operator.crunchydata.com/data=postgres" tail: 30 +- type: pod + selector: "job-name=major-upgrade-pgbackrest-restore" + tail: 300 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore diff --git a/e2e-tests/tests/major-upgrade/48-run-restore.yaml b/e2e-tests/tests/major-upgrade/48-run-restore.yaml index ccaf6697b4..9ca741c97d 100644 --- a/e2e-tests/tests/major-upgrade/48-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/48-run-restore.yaml @@ -5,3 +5,5 @@ metadata: spec: pgCluster: major-upgrade repoName: repo1 + options: + - --log-level-console=debug diff --git a/e2e-tests/tests/major-upgrade/50-assert.yaml b/e2e-tests/tests/major-upgrade/50-assert.yaml index 14332948f5..280e7084f0 100644 --- a/e2e-tests/tests/major-upgrade/50-assert.yaml +++ b/e2e-tests/tests/major-upgrade/50-assert.yaml @@ -5,6 +5,13 @@ commands: - script: |- kubectl -n ${NAMESPACE} get pg,pod,job sleep 5 +collectors: +- type: pod + selector: "postgres-operator.crunchydata.com/data=postgres" + tail: 30 +- type: pod + selector: "postgres-operator.crunchydata.com/pgupgrade=13-to-14" + tail: 200 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster diff --git a/e2e-tests/tests/major-upgrade/58-assert.yaml b/e2e-tests/tests/major-upgrade/58-assert.yaml index 97161e5125..a6f87ed937 100644 --- a/e2e-tests/tests/major-upgrade/58-assert.yaml +++ b/e2e-tests/tests/major-upgrade/58-assert.yaml @@ -18,11 +18,14 @@ commands: | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null done - sleep 30 + sleep 15 collectors: - type: pod selector: "postgres-operator.crunchydata.com/data=postgres" tail: 30 +- type: pod + selector: "job-name=major-upgrade-pgbackrest-restore" + tail: 300 --- apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore diff --git a/e2e-tests/tests/major-upgrade/58-run-restore.yaml b/e2e-tests/tests/major-upgrade/58-run-restore.yaml index 5df2121b39..e023013780 100644 --- a/e2e-tests/tests/major-upgrade/58-run-restore.yaml +++ b/e2e-tests/tests/major-upgrade/58-run-restore.yaml @@ -5,3 +5,5 @@ metadata: spec: pgCluster: major-upgrade repoName: repo1 + options: + - --log-level-console=debug diff --git a/e2e-tests/tests/major-upgrade/59-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/59-read-from-primary.yaml index 0549c2c862..5f3d5ceba8 100644 --- a/e2e-tests/tests/major-upgrade/59-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/59-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 49-read-from-primary --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 59-read-from-primary --from-literal=data="${data}" From 0ae6b245bda406566a073bb1407618473c7fe6e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Fri, 11 Apr 2025 18:16:10 +0300 Subject: [PATCH 010/300] stanza-delete --- .../major-upgrade/23-recreate-stanza.yaml | 36 +++++++++++++++++++ .../tests/major-upgrade/23-switch-wal.yaml | 18 ---------- .../{22-assert.yaml => 27-assert.yaml} | 0 ...{22-run-backup.yaml => 27-run-backup.yaml} | 0 .../major-upgrade/33-recreate-stanza.yaml | 36 +++++++++++++++++++ .../tests/major-upgrade/33-switch-wal.yaml | 18 ---------- .../{32-assert.yaml => 37-assert.yaml} | 0 ...{32-run-backup.yaml => 37-run-backup.yaml} | 0 .../major-upgrade/43-recreate-stanza.yaml | 36 +++++++++++++++++++ .../tests/major-upgrade/43-switch-wal.yaml | 18 ---------- .../{42-assert.yaml => 47-assert.yaml} | 0 ...{42-run-backup.yaml => 47-run-backup.yaml} | 0 .../major-upgrade/53-recreate-stanza.yaml | 36 +++++++++++++++++++ .../tests/major-upgrade/53-switch-wal.yaml | 18 ---------- .../{52-assert.yaml => 57-assert.yaml} | 0 ...{52-run-backup.yaml => 57-run-backup.yaml} | 0 16 files changed, 144 insertions(+), 72 deletions(-) create mode 100644 e2e-tests/tests/major-upgrade/23-recreate-stanza.yaml delete mode 100644 e2e-tests/tests/major-upgrade/23-switch-wal.yaml rename e2e-tests/tests/major-upgrade/{22-assert.yaml => 27-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{22-run-backup.yaml => 27-run-backup.yaml} (100%) create mode 100644 e2e-tests/tests/major-upgrade/33-recreate-stanza.yaml delete mode 100644 e2e-tests/tests/major-upgrade/33-switch-wal.yaml rename e2e-tests/tests/major-upgrade/{32-assert.yaml => 37-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{32-run-backup.yaml => 37-run-backup.yaml} (100%) create mode 100644 e2e-tests/tests/major-upgrade/43-recreate-stanza.yaml delete mode 100644 e2e-tests/tests/major-upgrade/43-switch-wal.yaml rename e2e-tests/tests/major-upgrade/{42-assert.yaml => 47-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{42-run-backup.yaml => 47-run-backup.yaml} (100%) create mode 100644 e2e-tests/tests/major-upgrade/53-recreate-stanza.yaml delete mode 100644 e2e-tests/tests/major-upgrade/53-switch-wal.yaml rename e2e-tests/tests/major-upgrade/{52-assert.yaml => 57-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{52-run-backup.yaml => 57-run-backup.yaml} (100%) diff --git a/e2e-tests/tests/major-upgrade/23-recreate-stanza.yaml b/e2e-tests/tests/major-upgrade/23-recreate-stanza.yaml new file mode 100644 index 0000000000..1e38f9309e --- /dev/null +++ b/e2e-tests/tests/major-upgrade/23-recreate-stanza.yaml @@ -0,0 +1,36 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 300 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- touch /pgdata/sleep-forever + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stop + done + + pod=$(kubectl get -n ${NAMESPACE} pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | tail -n 1 | awk '{print $1}') + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl pause + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pg_ctl -D /pgdata/pg14 stop + done + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-delete + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug start + kubectl -n ${NAMESPACE} exec ${pod} -- rm /pgdata/sleep-forever + done + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl resume + + # give some time to patroni for starting postgres + sleep 90 + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-create diff --git a/e2e-tests/tests/major-upgrade/23-switch-wal.yaml b/e2e-tests/tests/major-upgrade/23-switch-wal.yaml deleted file mode 100644 index 23c0729adb..0000000000 --- a/e2e-tests/tests/major-upgrade/23-switch-wal.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 90 - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - run_psql_local \ - 'checkpoint' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - run_psql_local \ - 'select pg_switch_wal()' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - - sleep 60 diff --git a/e2e-tests/tests/major-upgrade/22-assert.yaml b/e2e-tests/tests/major-upgrade/27-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/22-assert.yaml rename to e2e-tests/tests/major-upgrade/27-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/22-run-backup.yaml b/e2e-tests/tests/major-upgrade/27-run-backup.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/22-run-backup.yaml rename to e2e-tests/tests/major-upgrade/27-run-backup.yaml diff --git a/e2e-tests/tests/major-upgrade/33-recreate-stanza.yaml b/e2e-tests/tests/major-upgrade/33-recreate-stanza.yaml new file mode 100644 index 0000000000..d2aaa59ab1 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/33-recreate-stanza.yaml @@ -0,0 +1,36 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 300 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- touch /pgdata/sleep-forever + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stop + done + + pod=$(kubectl get -n ${NAMESPACE} pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | tail -n 1 | awk '{print $1}') + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl pause + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pg_ctl -D /pgdata/pg15 stop + done + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-delete + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug start + kubectl -n ${NAMESPACE} exec ${pod} -- rm /pgdata/sleep-forever + done + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl resume + + # give some time to patroni for starting postgres + sleep 90 + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-create diff --git a/e2e-tests/tests/major-upgrade/33-switch-wal.yaml b/e2e-tests/tests/major-upgrade/33-switch-wal.yaml deleted file mode 100644 index 23c0729adb..0000000000 --- a/e2e-tests/tests/major-upgrade/33-switch-wal.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 90 - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - run_psql_local \ - 'checkpoint' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - run_psql_local \ - 'select pg_switch_wal()' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - - sleep 60 diff --git a/e2e-tests/tests/major-upgrade/32-assert.yaml b/e2e-tests/tests/major-upgrade/37-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/32-assert.yaml rename to e2e-tests/tests/major-upgrade/37-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/32-run-backup.yaml b/e2e-tests/tests/major-upgrade/37-run-backup.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/32-run-backup.yaml rename to e2e-tests/tests/major-upgrade/37-run-backup.yaml diff --git a/e2e-tests/tests/major-upgrade/43-recreate-stanza.yaml b/e2e-tests/tests/major-upgrade/43-recreate-stanza.yaml new file mode 100644 index 0000000000..58b18bc4cd --- /dev/null +++ b/e2e-tests/tests/major-upgrade/43-recreate-stanza.yaml @@ -0,0 +1,36 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 300 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- touch /pgdata/sleep-forever + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stop + done + + pod=$(kubectl get -n ${NAMESPACE} pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | tail -n 1 | awk '{print $1}') + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl pause + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pg_ctl -D /pgdata/pg16 stop + done + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-delete + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug start + kubectl -n ${NAMESPACE} exec ${pod} -- rm /pgdata/sleep-forever + done + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl resume + + # give some time to patroni for starting postgres + sleep 90 + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-create diff --git a/e2e-tests/tests/major-upgrade/43-switch-wal.yaml b/e2e-tests/tests/major-upgrade/43-switch-wal.yaml deleted file mode 100644 index 23c0729adb..0000000000 --- a/e2e-tests/tests/major-upgrade/43-switch-wal.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 90 - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - run_psql_local \ - 'checkpoint' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - run_psql_local \ - 'select pg_switch_wal()' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - - sleep 60 diff --git a/e2e-tests/tests/major-upgrade/42-assert.yaml b/e2e-tests/tests/major-upgrade/47-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/42-assert.yaml rename to e2e-tests/tests/major-upgrade/47-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/42-run-backup.yaml b/e2e-tests/tests/major-upgrade/47-run-backup.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/42-run-backup.yaml rename to e2e-tests/tests/major-upgrade/47-run-backup.yaml diff --git a/e2e-tests/tests/major-upgrade/53-recreate-stanza.yaml b/e2e-tests/tests/major-upgrade/53-recreate-stanza.yaml new file mode 100644 index 0000000000..49742c96a3 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/53-recreate-stanza.yaml @@ -0,0 +1,36 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - timeout: 300 + script: |- + set -o errexit + set -o xtrace + + source ../../functions + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- touch /pgdata/sleep-forever + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stop + done + + pod=$(kubectl get -n ${NAMESPACE} pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | tail -n 1 | awk '{print $1}') + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl pause + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pg_ctl -D /pgdata/pg17 stop + done + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-delete + + for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug start + kubectl -n ${NAMESPACE} exec ${pod} -- rm /pgdata/sleep-forever + done + + kubectl -n ${NAMESPACE} exec ${pod} -- patronictl resume + + # give some time to patroni for starting postgres + sleep 90 + + kubectl -n ${NAMESPACE} exec ${pod} -- pgbackrest --stanza=db --log-level-console=debug stanza-create diff --git a/e2e-tests/tests/major-upgrade/53-switch-wal.yaml b/e2e-tests/tests/major-upgrade/53-switch-wal.yaml deleted file mode 100644 index 23c0729adb..0000000000 --- a/e2e-tests/tests/major-upgrade/53-switch-wal.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - timeout: 90 - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - run_psql_local \ - 'checkpoint' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - run_psql_local \ - 'select pg_switch_wal()' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - - sleep 60 diff --git a/e2e-tests/tests/major-upgrade/52-assert.yaml b/e2e-tests/tests/major-upgrade/57-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/52-assert.yaml rename to e2e-tests/tests/major-upgrade/57-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/52-run-backup.yaml b/e2e-tests/tests/major-upgrade/57-run-backup.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/52-run-backup.yaml rename to e2e-tests/tests/major-upgrade/57-run-backup.yaml From 1f8703f6e62de38b87eb4185482dab6f7a4f8aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Fri, 11 Apr 2025 18:32:12 +0300 Subject: [PATCH 011/300] fix --- e2e-tests/tests/major-upgrade/59-assert.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/major-upgrade/59-assert.yaml b/e2e-tests/tests/major-upgrade/59-assert.yaml index cb611a153c..539ce9a2ad 100644 --- a/e2e-tests/tests/major-upgrade/59-assert.yaml +++ b/e2e-tests/tests/major-upgrade/59-assert.yaml @@ -5,7 +5,7 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 49-read-from-primary + name: 59-read-from-primary data: data: |2- 100500 From a71d12176415cce33c6b6770b8212ecfd87f2427 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 14 Apr 2025 15:18:36 +0300 Subject: [PATCH 012/300] K8SPG 741 Merge upstream changes for 2.7.0 (#1094) * Remove Postgres 10 from APIs and Tests Issue: PGO-614 * Remove major-upgrade-missing-image KUTTL test from e2e-other This test duplicates what's in the main e2e folder. * Remove json:omitempty from required fields This version of controller-gen ignores "validation:Required" markers when the struct tag has "json:omitempty". Issue: PGO-1748 * October updates to workflows and README Issue: PGO-738 Issue: PGO-1829 * run make generate * Update field manager for deployment id / configmap (#4020) For some reason, this was originally created without PGO listed as the manager for the configmap used by upgrade check. * Check that snapshot.Status is not nil when checking Status properties. * Move SQL escape functions to the Postgres package These are specific to Postgres. Add tests and remove unused functions. * Enable the "errchkjson" linter This is part of the "bugs" preset of golangci-lint. The "check-error-free-encoding" setting is recommended upstream. * Quiet a number of "gosec" warnings in tests These are ignored by golangci-lint by default. * Create warning event when postgres version is EOL. * Consistently use either pointer or value receivers Subtle bugs can arise when mixing the two. A type is more coherent when it behaves as only one of (1) a value or (2) a reference. A new linter identifies this situation but does not yet account for unmarshal methods on value types. See: https://go.dev/wiki/CodeReviewComments#receiver-type See: https://go.dev/wiki/MethodSets * fix errors and tests * Add functions to safely convert unstructured types The default unstructured converter does not complain if you try to convert a list to an object or vice versa. It also expects to be called with an empty target object. * fix library * Run upgrade tests in isolated namespaces * fix test * Remove github.com/pkg/errors from tests Tests already report the line on which an assert fails, and the standard "errors" packages unwraps errors. * fix imports * Load VolumeSnapshot CRDs from the client Go module during tests We only use these CRD files in Go tests, and Go has already downloaded them as part of the module we import for serializing API objects. * fix issues * Add default container annotation (#4031) * Add default container annotation Since K8s 1.21, the kubectl.kubernetes.io/default-container annotation can be added to set a default container, removing the need for a -c flag or eliminating the message about defaulting Note: the `-c` flag can still be used to refer to a different, non-default container. Issues: [PGO-1941] * bring back GOBIN='/hack/tools', run make clean-deprecated * fix one more test * commit generated * revert change on aws sdk go * Add an interface for querying available Kubernetes APIs * conflicts fixing * Explicitly enable "hot_standby" during restore This parameter has been enabled by default since Postgres 10 and is unlikely to change, but we want the behavior, so we should set it. * Consider pg_ctl successful when progress is made There is a race when using pg_ctl start --wait: - pg_ctl starts Postgres - Postgres begins recovery, detects a parameter requires restart, and exits - pg_ctl reports that Postgres did not start Now we look at the LSN reported by pg_controldata to determine if Postgres made any progress during a "failed" start. Issue: PGO-1945 * Tidy the pgBackRest restore command using slices Having these lines broken into string slices allows for Go comments that explain them without presenting those comments in YAML at runtime. This also: - Uses the postgres.ParameterSet type to accumulate Postgres settings. A new String method renders those values safely for use in postgresql.conf. - Disables localization using LC_ALL=C in calls to pg_controldata before we parse its output. - Removes commands to change permissions on tablespace directories; pgBackRest handles this for us now. - Passes command line parameters to Postgres using "-c" rather than "--" long flags. Both work on Linux, but the former works on all systems. - Explains why we need a large timeout for "pg_ctl --wait" and configures it once using the PGCTLTIMEOUT environment variable. * run make generate for main * features and conflicts and main * Stop turning runners context.Canceled error into nil. * Add a Comparison for YAML that contains a string * remove k8s helper functions that are not used * Use multiple processors when PGUpgrade is given CPU resources The --jobs flag allows for some aspects of pg_upgrade to operate in parallel. The documentation says: This option can dramatically reduce the time to upgrade a multi-database server running on a multiprocessor machine. Issue: PGO-1958 See: https://www.postgresql.org/docs/current/pgupgrade.html * bring back the error on marshaling * fix tests * run go fmt * larget timeout on assert 01 * add sts default annotation if version over 2.7 * fix annotations for pgbouncer and pgbackrest * fix unit test internal/controller/postgrescluster/pgbouncer_test.go * run go fmt --------- Co-authored-by: TJ Moore Co-authored-by: Chris Bandy Co-authored-by: Drew Sessler Co-authored-by: Benjamin Blattberg --- .golangci.next.yaml | 10 +- .golangci.yaml | 20 +- Makefile | 13 +- ...s-operator.crunchydata.com_pgupgrades.yaml | 2703 ----------------- ...ator.crunchydata.com_postgresclusters.yaml | 4 - cmd/postgres-operator/main.go | 7 +- ...ator.crunchydata.com_postgresclusters.yaml | 4 - config/manager/manager.yaml | 22 +- deploy/bundle.yaml | 4 - deploy/crd.yaml | 4 - deploy/cw-bundle.yaml | 4 - .../tests/upgrade-consistency/01-assert.yaml | 2 +- examples/postgrescluster/postgrescluster.yaml | 5 +- go.mod | 3 +- go.sum | 2 + internal/controller/pgupgrade/jobs.go | 52 +- internal/controller/pgupgrade/jobs_test.go | 100 +- internal/controller/pgupgrade/world_test.go | 4 +- .../postgrescluster/cluster_test.go | 110 +- .../controller/postgrescluster/controller.go | 10 + .../postgrescluster/controller_test.go | 66 +- .../controller/postgrescluster/instance.go | 16 +- .../postgrescluster/instance_test.go | 8 +- .../postgrescluster/patroni_test.go | 12 +- .../controller/postgrescluster/pgadmin.go | 6 +- .../postgrescluster/pgadmin_test.go | 5 +- .../controller/postgrescluster/pgbackrest.go | 87 +- .../postgrescluster/pgbackrest_test.go | 31 +- .../controller/postgrescluster/pgbouncer.go | 12 +- .../postgrescluster/pgbouncer_test.go | 5 +- .../controller/postgrescluster/pki_test.go | 11 +- .../postgrescluster/postgres_test.go | 2 +- .../controller/postgrescluster/snapshots.go | 6 +- .../postgrescluster/snapshots_test.go | 183 +- .../controller/postgrescluster/suite_test.go | 21 +- .../controller/postgrescluster/volumes.go | 12 +- internal/controller/runtime/conversion.go | 73 + .../controller/runtime/conversion_test.go | 46 + .../standalone_pgadmin/statefulset.go | 7 +- .../standalone_pgadmin/statefulset_test.go | 3 + .../controller/standalone_pgadmin/users.go | 6 +- .../standalone_pgadmin/users_test.go | 58 +- .../standalone_pgadmin/volume_test.go | 2 +- internal/feature/features.go | 61 +- internal/feature/features_test.go | 23 +- internal/kubeapi/patch.go | 56 +- internal/logging/logr.go | 14 +- internal/logging/logrus_test.go | 2 +- internal/naming/annotations.go | 5 + internal/patroni/api_test.go | 8 +- internal/patroni/config_test.go | 34 +- internal/pgadmin/config.go | 2 +- internal/pgbackrest/config.go | 194 +- internal/pgbackrest/config_test.go | 54 +- internal/pgbouncer/postgres.go | 12 +- internal/pgbouncer/postgres_test.go | 16 +- internal/pgbouncer/reconcile_test.go | 2 +- internal/pgmonitor/postgres.go | 6 +- internal/pmm/hba.go | 6 +- internal/postgres/hba.go | 20 +- internal/postgres/hba_test.go | 2 +- internal/postgres/parameters.go | 30 +- internal/postgres/parameters_test.go | 4 + internal/postgres/sql.go | 22 + internal/postgres/sql_test.go | 16 + internal/postgres/versions.go | 26 + internal/postgres/versions_test.go | 34 + internal/registration/runner.go | 4 - internal/testing/cmp/cmp.go | 9 + internal/testing/require/kubernetes.go | 34 +- internal/upgradecheck/header.go | 16 +- internal/upgradecheck/header_test.go | 18 +- internal/upgradecheck/helpers_test.go | 25 - internal/upgradecheck/http.go | 2 +- internal/upgradecheck/http_test.go | 2 +- internal/util/util.go | 62 - .../v1beta1/crunchy_bridgecluster_types.go | 8 +- .../v1beta1/pgbackrest_types.go | 6 +- .../v1beta1/shared_types.go | 9 +- .../v1beta1/shared_types_test.go | 15 +- .../v1beta1/zz_generated.deepcopy.go | 17 +- .../01--valid-upgrade.yaml | 11 - .../01-assert.yaml | 10 - .../10--cluster.yaml | 23 - .../10-assert.yaml | 12 - .../11--shutdown-cluster.yaml | 8 - .../11-assert.yaml | 11 - .../12--start-and-update-version.yaml | 17 - .../12-assert.yaml | 31 - .../13--shutdown-cluster.yaml | 8 - .../13-assert.yaml | 11 - .../14--annotate-cluster.yaml | 8 - .../14-assert.yaml | 22 - .../15--start-cluster.yaml | 10 - .../15-assert.yaml | 18 - .../16-check-pgbackrest.yaml | 6 - .../17--check-version.yaml | 39 - .../17-assert.yaml | 7 - .../major-upgrade-missing-image/README.md | 36 - .../01--valid-upgrade.yaml | 2 +- .../10--cluster.yaml | 2 +- .../e2e/major-upgrade-missing-image/README.md | 2 +- 102 files changed, 1144 insertions(+), 3787 deletions(-) delete mode 100644 build/crd/crunchy/generated/postgres-operator.crunchydata.com_pgupgrades.yaml create mode 100644 internal/controller/runtime/conversion.go create mode 100644 internal/controller/runtime/conversion_test.go create mode 100644 internal/postgres/sql.go create mode 100644 internal/postgres/sql_test.go create mode 100644 internal/postgres/versions.go create mode 100644 internal/postgres/versions_test.go delete mode 100644 internal/util/util.go delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/01--valid-upgrade.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/01-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/10--cluster.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/10-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/11--shutdown-cluster.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/11-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/12--start-and-update-version.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/12-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/13--shutdown-cluster.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/13-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/14--annotate-cluster.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/14-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/15--start-cluster.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/15-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/16-check-pgbackrest.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/17--check-version.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/17-assert.yaml delete mode 100644 testing/kuttl/e2e-other/major-upgrade-missing-image/README.md diff --git a/.golangci.next.yaml b/.golangci.next.yaml index 1be9e93d73..c501542273 100644 --- a/.golangci.next.yaml +++ b/.golangci.next.yaml @@ -10,7 +10,6 @@ linters: enable: - contextcheck - err113 - - errchkjson - gocritic - godot - godox @@ -28,13 +27,16 @@ linters: - wastedassign issues: + exclude-rules: + # We call external linters when they are installed: Flake8, ShellCheck, etc. + - linters: [gosec] + path: '_test[.]go$' + text: 'G204: Subprocess launched with variable' + # https://github.com/golangci/golangci-lint/issues/2239 exclude-use-default: false linters-settings: - errchkjson: - check-error-free-encoding: true - thelper: # https://github.com/kulti/thelper/issues/27 tb: { begin: true, first: true } diff --git a/.golangci.yaml b/.golangci.yaml index 7d35b967ba..3618ff73b3 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -3,7 +3,6 @@ linters: disable: - contextcheck - - errchkjson - gci - gofumpt - goimports @@ -47,6 +46,15 @@ linters-settings: - pkg: github.com/percona/percona-postgresql-operator/internal/testing/* desc: The "internal/testing" packages should be used only in tests. + tests: + files: ['$test'] + deny: + - pkg: github.com/pkg/errors + desc: Use the "errors" package unless you are interacting with stack traces. + + errchkjson: + check-error-free-encoding: true + exhaustive: default-signifies-exhaustive: true @@ -73,6 +81,10 @@ run: build-tags: - envtest issues: - exclude-dirs: - - pkg/generated - - hack + exclude-generated: strict + exclude-rules: + # These value types have unmarshal methods. + # https://github.com/raeperd/recvcheck/issues/7 + - linters: [recvcheck] + path: internal/pki/pki.go + text: 'methods of "(Certificate|PrivateKey)"' diff --git a/Makefile b/Makefile index e8f2fa8a09..472bc36f27 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,6 @@ PGMONITOR_DIR ?= hack/tools/pgmonitor PGMONITOR_VERSION ?= v4.11.0 QUERIES_CONFIG_DIR ?= hack/tools/queries -EXTERNAL_SNAPSHOTTER_DIR ?= hack/tools/external-snapshotter -EXTERNAL_SNAPSHOTTER_VERSION ?= v8.0.1 - # Buildah's "build" used to be "bud". Use the alias to be compatible for a while. BUILDAH_BUILD ?= buildah bud @@ -56,12 +53,6 @@ get-pgmonitor: cp -r '$(PGMONITOR_DIR)/postgres_exporter/common/.' '${QUERIES_CONFIG_DIR}' cp '$(PGMONITOR_DIR)/postgres_exporter/linux/queries_backrest.yml' '${QUERIES_CONFIG_DIR}' -.PHONY: get-external-snapshotter -get-external-snapshotter: - git -C '$(dir $(EXTERNAL_SNAPSHOTTER_DIR))' clone https://github.com/kubernetes-csi/external-snapshotter.git || git -C '$(EXTERNAL_SNAPSHOTTER_DIR)' fetch origin - @git -C '$(EXTERNAL_SNAPSHOTTER_DIR)' checkout '$(EXTERNAL_SNAPSHOTTER_VERSION)' - @git -C '$(EXTERNAL_SNAPSHOTTER_DIR)' config pull.ff only - .PHONY: clean clean: ## Clean resources clean: clean-deprecated @@ -209,7 +200,7 @@ check: get-pgmonitor check-envtest: ## Run check using envtest and a mock kube api check-envtest: ENVTEST_USE = hack/tools/setup-envtest --bin-dir=$(CURDIR)/hack/tools/envtest use $(ENVTEST_K8S_VERSION) check-envtest: SHELL = bash -check-envtest: get-pgmonitor get-external-snapshotter +check-envtest: get-pgmonitor tools/setup-envtest GOBIN='$(CURDIR)/hack/tools' $(GO) install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest @$(ENVTEST_USE) --print=overview && echo source <($(ENVTEST_USE) --print=env) && PGO_NAMESPACE="postgres-operator" QUERIES_CONFIG_DIR="$(CURDIR)/${QUERIES_CONFIG_DIR}" \ @@ -221,7 +212,7 @@ check-envtest: get-pgmonitor get-external-snapshotter # make check-envtest-existing PGO_TEST_TIMEOUT_SCALE=1.2 .PHONY: check-envtest-existing check-envtest-existing: ## Run check using envtest and an existing kube api -check-envtest-existing: get-pgmonitor get-external-snapshotter +check-envtest-existing: get-pgmonitor check-envtest-existing: createnamespaces kubectl apply --server-side -k ./config/dev USE_EXISTING_CLUSTER=true PGO_NAMESPACE="postgres-operator" QUERIES_CONFIG_DIR="$(CURDIR)/${QUERIES_CONFIG_DIR}" \ diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_pgupgrades.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_pgupgrades.yaml deleted file mode 100644 index ceffaff5ee..0000000000 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_pgupgrades.yaml +++ /dev/null @@ -1,2703 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.5 - name: pgupgrades.postgres-operator.crunchydata.com -spec: - group: postgres-operator.crunchydata.com - names: - kind: PGUpgrade - listKind: PGUpgradeList - plural: pgupgrades - singular: pgupgrade - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: PGUpgrade is the Schema for the pgupgrades API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: PGUpgradeSpec defines the desired state of PGUpgrade - properties: - affinity: - description: |- - Scheduling constraints of the PGUpgrade pod. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the - pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with the - corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the corresponding - nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate - this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. - avoid putting this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - fromPostgresVersion: - description: The major version of PostgreSQL before the upgrade. - maximum: 17 - minimum: 12 - type: integer - image: - description: The image name to use for major PostgreSQL upgrades. - type: string - imagePullPolicy: - description: |- - ImagePullPolicy is used to determine when Kubernetes will attempt to - pull (download) container images. - More info: https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy - enum: - - Always - - Never - - IfNotPresent - type: string - imagePullSecrets: - description: |- - The image pull secrets used to pull from a private registry. - Changing this value causes all running PGUpgrade pods to restart. - https://k8s.io/docs/tasks/configure-pod-container/pull-image-private-registry/ - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - type: array - initContainers: - description: Init container to run before the upgrade container. - items: - description: A single application container that you want to run - within a pod. - properties: - args: - description: |- - Arguments to the entrypoint. - The container image's CMD is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - description: |- - Entrypoint array. Not executed within a shell. - The container image's ENTRYPOINT is used if this is not provided. - Variable references $(VAR_NAME) are expanded using the container's environment. If a variable - cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will - produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless - of whether the variable exists or not. Cannot be updated. - More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - description: |- - List of environment variables to set in the container. - Cannot be updated. - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. - type: string - value: - description: |- - Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in the container and - any service environment variables. If a variable cannot be resolved, - the reference in the input string will be unchanged. Double $$ are reduced - to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless of whether the variable - exists or not. - Defaults to "". - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap or - its key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: |- - Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, - spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the - specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: |- - Selects a resource of the container: only resources limits and requests - (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - description: |- - List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple - sources, the value associated with the last source will take precedence. - Values defined by an Env with a duplicate key will take precedence. - Cannot be updated. - items: - description: EnvFromSource represents the source of a set - of ConfigMaps - properties: - configMapRef: - description: The ConfigMap to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the ConfigMap must be - defined - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. - type: string - secretRef: - description: The Secret to select from - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - description: |- - Container image name. - More info: https://kubernetes.io/docs/concepts/containers/images - This field is optional to allow higher level config management to default or override - container images in workload controllers like Deployments and StatefulSets. - type: string - imagePullPolicy: - description: |- - Image pull policy. - One of Always, Never, IfNotPresent. - Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/containers/images#updating-images - type: string - lifecycle: - description: |- - Actions that the management system should take in response to container lifecycle events. - Cannot be updated. - properties: - postStart: - description: |- - PostStart is called immediately after a container is created. If the handler fails, - the container is terminated and restarted according to its restart policy. - Other management of the container blocks until the hook completes. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies a command to execute in - the container. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies an HTTP GET request to - perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents a duration that the container - should sleep. - properties: - seconds: - description: Seconds is the number of seconds to - sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for backward compatibility. There is no validation of this field and - lifecycle hooks will fail at runtime when it is specified. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - description: |- - PreStop is called immediately before a container is terminated due to an - API request or management event such as liveness/startup probe failure, - preemption, resource contention, etc. The handler is not called if the - container crashes or exits. The Pod's termination grace period countdown begins before the - PreStop hook is executed. Regardless of the outcome of the handler, the - container will eventually terminate within the Pod's termination grace - period (unless delayed by finalizers). Other management of the container blocks until the hook completes - or until the termination grace period is reached. - More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks - properties: - exec: - description: Exec specifies a command to execute in - the container. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - description: HTTPGet specifies an HTTP GET request to - perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. - HTTP allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - sleep: - description: Sleep represents a duration that the container - should sleep. - properties: - seconds: - description: Seconds is the number of seconds to - sleep. - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - description: |- - Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept - for backward compatibility. There is no validation of this field and - lifecycle hooks will fail at runtime when it is specified. - properties: - host: - description: 'Optional: Host name to connect to, - defaults to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - description: |- - Periodic probe of container liveness. - Container will be restarted if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies a command to execute in the - container. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies a GRPC HealthCheckRequest. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies an HTTP GET request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP - allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies a connection to a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, defaults - to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - name: - description: |- - Name of the container specified as a DNS_LABEL. - Each container in a pod must have a unique name (DNS_LABEL). - Cannot be updated. - type: string - ports: - description: |- - List of ports to expose from the container. Not specifying a port here - DOES NOT prevent that port from being exposed. Any port which is - listening on the default "0.0.0.0" address inside a container will be - accessible from the network. - Modifying this array with strategic merge patch may corrupt the data. - For more information See https://github.com/kubernetes/kubernetes/issues/108255. - Cannot be updated. - items: - description: ContainerPort represents a network port in a - single container. - properties: - containerPort: - description: |- - Number of port to expose on the pod's IP address. - This must be a valid port number, 0 < x < 65536. - format: int32 - type: integer - hostIP: - description: What host IP to bind the external port to. - type: string - hostPort: - description: |- - Number of port to expose on the host. - If specified, this must be a valid port number, 0 < x < 65536. - If HostNetwork is specified, this must match ContainerPort. - Most containers do not need this. - format: int32 - type: integer - name: - description: |- - If specified, this must be an IANA_SVC_NAME and unique within the pod. Each - named port in a pod must have a unique name. Name for the port that can be - referred to by services. - type: string - protocol: - default: TCP - description: |- - Protocol for port. Must be UDP, TCP, or SCTP. - Defaults to "TCP". - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - description: |- - Periodic probe of container service readiness. - Container will be removed from service endpoints if the probe fails. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies a command to execute in the - container. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies a GRPC HealthCheckRequest. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies an HTTP GET request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP - allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies a connection to a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, defaults - to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - resizePolicy: - description: Resources resize policy for the container. - items: - description: ContainerResizePolicy represents resource resize - policy for the container. - properties: - resourceName: - description: |- - Name of the resource to which this resource resize policy applies. - Supported values: cpu, memory. - type: string - restartPolicy: - description: |- - Restart policy to apply when specified resource is resized. - If not specified, it defaults to NotRequired. - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - description: |- - Compute Resources required by this container. - Cannot be updated. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - restartPolicy: - description: |- - RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, - the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: - this init container will be continually restarted on - exit until all regular containers have terminated. Once all regular - containers have completed, all init containers with restartPolicy "Always" - will be shut down. This lifecycle differs from normal init containers and - is often referred to as a "sidecar" container. Although this init - container still starts in the init container sequence, it does not wait - for the container to complete before proceeding to the next init - container. Instead, the next init container starts immediately after this - init container is started, or after any startupProbe has successfully - completed. - type: string - securityContext: - description: |- - SecurityContext defines the security options the container should be run with. - If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. - More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ - properties: - allowPrivilegeEscalation: - description: |- - AllowPrivilegeEscalation controls whether a process can gain more - privileges than its parent process. This bool directly controls if - the no_new_privs flag will be set on the container process. - AllowPrivilegeEscalation is true always when the container is: - 1) run as Privileged - 2) has CAP_SYS_ADMIN - Note that this field cannot be set when spec.os.name is windows. - type: boolean - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by this container. If set, this profile - overrides the pod's appArmorProfile. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - capabilities: - description: |- - The capabilities to add/drop when running containers. - Defaults to the default set of capabilities granted by the container runtime. - Note that this field cannot be set when spec.os.name is windows. - properties: - add: - description: Added capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - drop: - description: Removed capabilities - items: - description: Capability represent POSIX capabilities - type - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - description: |- - Run container in privileged mode. - Processes in privileged containers are essentially equivalent to root on the host. - Defaults to false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - procMount: - description: |- - procMount denotes the type of proc mount to use for the containers. - The default value is Default which uses the container runtime defaults for - readonly paths and masked paths. - This requires the ProcMountType feature flag to be enabled. - Note that this field cannot be set when spec.os.name is windows. - type: string - readOnlyRootFilesystem: - description: |- - Whether this container has a read-only root filesystem. - Default is false. - Note that this field cannot be set when spec.os.name is windows. - type: boolean - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxOptions: - description: |- - The SELinux context to be applied to the container. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that applies - to the container. - type: string - role: - description: Role is a SELinux role label that applies - to the container. - type: string - type: - description: Type is a SELinux type label that applies - to the container. - type: string - user: - description: User is a SELinux user label that applies - to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by this container. If seccomp options are - provided at both the pod & container level, the container options - override the pod options. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: - - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options from the PodSecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name of the - GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object - startupProbe: - description: |- - StartupProbe indicates that the Pod has successfully initialized. - If specified, no other probes are executed until this completes successfully. - If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. - This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, - when it might take a long time to load data or warm a cache, than during steady-state operation. - This cannot be updated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - properties: - exec: - description: Exec specifies a command to execute in the - container. - properties: - command: - description: |- - Command is the command line to execute inside the container, the working directory for the - command is root ('/') in the container's filesystem. The command is simply exec'd, it is - not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use - a shell, you need to explicitly call out to that shell. - Exit status of 0 is treated as live/healthy and non-zero is unhealthy. - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. - Defaults to 3. Minimum value is 1. - format: int32 - type: integer - grpc: - description: GRPC specifies a GRPC HealthCheckRequest. - properties: - port: - description: Port number of the gRPC service. Number - must be in the range 1 to 65535. - format: int32 - type: integer - service: - default: "" - description: |- - Service is the name of the service to place in the gRPC HealthCheckRequest - (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - - If this is not specified, the default behavior is defined by gRPC. - type: string - required: - - port - type: object - httpGet: - description: HTTPGet specifies an HTTP GET request to perform. - properties: - host: - description: |- - Host name to connect to, defaults to the pod IP. You probably want to set - "Host" in httpHeaders instead. - type: string - httpHeaders: - description: Custom headers to set in the request. HTTP - allows repeated headers. - items: - description: HTTPHeader describes a custom header - to be used in HTTP probes - properties: - name: - description: |- - The header field name. - This will be canonicalized upon output, so case-variant names will be understood as the same header. - type: string - value: - description: The header field value - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - description: Path to access on the HTTP server. - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Name or number of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - scheme: - description: |- - Scheme to use for connecting to the host. - Defaults to HTTP. - type: string - required: - - port - type: object - initialDelaySeconds: - description: |- - Number of seconds after the container has started before liveness probes are initiated. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - periodSeconds: - description: |- - How often (in seconds) to perform the probe. - Default to 10 seconds. Minimum value is 1. - format: int32 - type: integer - successThreshold: - description: |- - Minimum consecutive successes for the probe to be considered successful after having failed. - Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. - format: int32 - type: integer - tcpSocket: - description: TCPSocket specifies a connection to a TCP port. - properties: - host: - description: 'Optional: Host name to connect to, defaults - to the pod IP.' - type: string - port: - anyOf: - - type: integer - - type: string - description: |- - Number or name of the port to access on the container. - Number must be in the range 1 to 65535. - Name must be an IANA_SVC_NAME. - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - description: |- - Optional duration in seconds the pod needs to terminate gracefully upon probe failure. - The grace period is the duration in seconds after the processes running in the pod are sent - a termination signal and the time when the processes are forcibly halted with a kill signal. - Set this value longer than the expected cleanup time for your process. - If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this - value overrides the value provided by the pod spec. - Value must be non-negative integer. The value zero indicates stop immediately via - the kill signal (no opportunity to shut down). - This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. - Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. - format: int64 - type: integer - timeoutSeconds: - description: |- - Number of seconds after which the probe times out. - Defaults to 1 second. Minimum value is 1. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - format: int32 - type: integer - type: object - stdin: - description: |- - Whether this container should allocate a buffer for stdin in the container runtime. If this - is not set, reads from stdin in the container will always result in EOF. - Default is false. - type: boolean - stdinOnce: - description: |- - Whether the container runtime should close the stdin channel after it has been opened by - a single attach. When stdin is true the stdin stream will remain open across multiple attach - sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the - first client attaches to stdin, and then remains open and accepts data until the client disconnects, - at which time stdin is closed and remains closed until the container is restarted. If this - flag is false, a container processes that reads from stdin will never receive an EOF. - Default is false - type: boolean - terminationMessagePath: - description: |- - Optional: Path at which the file to which the container's termination message - will be written is mounted into the container's filesystem. - Message written is intended to be brief final status, such as an assertion failure message. - Will be truncated by the node if greater than 4096 bytes. The total message length across - all containers will be limited to 12kb. - Defaults to /dev/termination-log. - Cannot be updated. - type: string - terminationMessagePolicy: - description: |- - Indicate how the termination message should be populated. File will use the contents of - terminationMessagePath to populate the container status message on both success and failure. - FallbackToLogsOnError will use the last chunk of container log output if the termination - message file is empty and the container exited with an error. - The log output is limited to 2048 bytes or 80 lines, whichever is smaller. - Defaults to File. - Cannot be updated. - type: string - tty: - description: |- - Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. - Default is false. - type: boolean - volumeDevices: - description: volumeDevices is the list of block devices to be - used by the container. - items: - description: volumeDevice describes a mapping of a raw block - device within a container. - properties: - devicePath: - description: devicePath is the path inside of the container - that the device will be mapped to. - type: string - name: - description: name must match the name of a persistentVolumeClaim - in the pod - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - description: |- - Pod volumes to mount into the container's filesystem. - Cannot be updated. - items: - description: VolumeMount describes a mounting of a Volume - within a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - description: |- - Container's working directory. - If not specified, the container runtime's default will be used, which - might be configured in the container image. - Cannot be updated. - type: string - required: - - name - type: object - type: array - metadata: - description: Metadata contains metadata for custom resources - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - postgresClusterName: - description: The name of the cluster to be updated - minLength: 1 - type: string - priorityClassName: - description: |- - Priority class name for the PGUpgrade pod. Changing this - value causes PGUpgrade pod to restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ - type: string - resources: - description: Resource requirements for the PGUpgrade container. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - toPostgresImage: - description: |- - The image name to use for PostgreSQL containers after upgrade. - When omitted, the value comes from an operator environment variable. - type: string - toPostgresVersion: - description: The major version of PostgreSQL to be upgraded to. - maximum: 17 - minimum: 13 - type: integer - tolerations: - description: |- - Tolerations of the PGUpgrade pod. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - volumeMounts: - description: The list of volume mounts to mount to upgrade pod. - items: - description: VolumeMount describes a mounting of a Volume within - a container. - properties: - mountPath: - description: |- - Path within the container at which the volume should be mounted. Must - not contain ':'. - type: string - mountPropagation: - description: |- - mountPropagation determines how mounts are propagated from the host - to container and the other way around. - When not set, MountPropagationNone is used. - This field is beta in 1.10. - When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified - (which defaults to None). - type: string - name: - description: This must match the Name of a Volume. - type: string - readOnly: - description: |- - Mounted read-only if true, read-write otherwise (false or unspecified). - Defaults to false. - type: boolean - recursiveReadOnly: - description: |- - RecursiveReadOnly specifies whether read-only mounts should be handled - recursively. - - If ReadOnly is false, this field has no meaning and must be unspecified. - - If ReadOnly is true, and this field is set to Disabled, the mount is not made - recursively read-only. If this field is set to IfPossible, the mount is made - recursively read-only, if it is supported by the container runtime. If this - field is set to Enabled, the mount is made recursively read-only if it is - supported by the container runtime, otherwise the pod will not be started and - an error will be generated to indicate the reason. - - If this field is set to IfPossible or Enabled, MountPropagation must be set to - None (or be unspecified, which defaults to None). - - If this field is not specified, it is treated as an equivalent of Disabled. - type: string - subPath: - description: |- - Path within the volume from which the container's volume should be mounted. - Defaults to "" (volume's root). - type: string - subPathExpr: - description: |- - Expanded path within the volume from which the container's volume should be mounted. - Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. - Defaults to "" (volume's root). - SubPathExpr and SubPath are mutually exclusive. - type: string - required: - - mountPath - - name - type: object - type: array - required: - - fromPostgresVersion - - postgresClusterName - - toPostgresVersion - type: object - status: - description: PGUpgradeStatus defines the observed state of PGUpgrade - properties: - conditions: - description: conditions represent the observations of PGUpgrade's - current state. - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - observedGeneration: - description: observedGeneration represents the .metadata.generation - on which the status was based. - format: int64 - minimum: 0 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index cd66d8f822..29d0220dbd 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -20829,10 +20829,6 @@ spec: type: description: The pgBackRest backup type for this Job type: string - required: - - cronJobName - - repo - - type type: object type: array type: object diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index d9acb41964..ad7ffadb88 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -92,7 +92,12 @@ func main() { assertNoError(err) assertNoError(features.Set(os.Getenv("PGO_FEATURE_GATES"))) - log.Info("feature gates enabled", "PGO_FEATURE_GATES", features.String()) + ctx = feature.NewContext(ctx, features) + log.Info("feature gates", + // These are set by the user + "PGO_FEATURE_GATES", feature.ShowAssigned(ctx), + // These are enabled, including features that are on by default + "enabled", feature.ShowEnabled(ctx)) cruntime.SetLogger(log) diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 5acc368675..751c1bac73 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -20727,10 +20727,6 @@ spec: type: description: The pgBackRest backup type for this Job type: string - required: - - cronJobName - - repo - - type type: object type: array type: object diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 24e770a958..961098410b 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -18,28 +18,28 @@ spec: fieldPath: metadata.namespace - name: CRUNCHY_DEBUG value: "true" - - name: RELATED_IMAGE_POSTGRES_15 - value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-15.7-1" - - name: RELATED_IMAGE_POSTGRES_15_GIS_3.3 - value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-gis:ubi8-15.7-3.3-1" - name: RELATED_IMAGE_POSTGRES_16 - value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.3-1" + value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.4-2" - name: RELATED_IMAGE_POSTGRES_16_GIS_3.3 - value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-gis:ubi8-16.3-3.3-1" + value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-gis:ubi8-16.4-3.3-2" - name: RELATED_IMAGE_POSTGRES_16_GIS_3.4 - value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-gis:ubi8-16.3-3.4-1" + value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-gis:ubi8-16.4-3.4-2" + - name: RELATED_IMAGE_POSTGRES_17 + value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-17.0-0" + - name: RELATED_IMAGE_POSTGRES_17_GIS_3.4 + value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-gis:ubi8-17.0-3.4-0" - name: RELATED_IMAGE_PGADMIN - value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgadmin4:ubi8-4.30-26" + value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgadmin4:ubi8-4.30-31" - name: RELATED_IMAGE_PGBACKREST - value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.51-1" + value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.53.1-0" - name: RELATED_IMAGE_PGBOUNCER - value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.22-1" + value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.23-0" - name: RELATED_IMAGE_PGEXPORTER value: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres-exporter:latest" - name: RELATED_IMAGE_PGUPGRADE value: "registry.developers.crunchydata.com/crunchydata/crunchy-upgrade:latest" - name: RELATED_IMAGE_STANDALONE_PGADMIN - value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgadmin4:ubi8-8.6-1" + value: "registry.developers.crunchydata.com/crunchydata/crunchy-pgadmin4:ubi8-8.12-0" securityContext: allowPrivilegeEscalation: false capabilities: { drop: [ALL] } diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index d463f3d349..9731f4a93c 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -47215,10 +47215,6 @@ spec: type: description: The pgBackRest backup type for this Job type: string - required: - - cronJobName - - repo - - type type: object type: array type: object diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 0f3446ac98..ea6fbf9b21 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -47215,10 +47215,6 @@ spec: type: description: The pgBackRest backup type for this Job type: string - required: - - cronJobName - - repo - - type type: object type: array type: object diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 45f1915b3c..b10296186e 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -47215,10 +47215,6 @@ spec: type: description: The pgBackRest backup type for this Job type: string - required: - - cronJobName - - repo - - type type: object type: array type: object diff --git a/e2e-tests/tests/upgrade-consistency/01-assert.yaml b/e2e-tests/tests/upgrade-consistency/01-assert.yaml index 1b44e68cfc..c5baa6caef 100644 --- a/e2e-tests/tests/upgrade-consistency/01-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 180 +timeout: 300 --- kind: StatefulSet apiVersion: apps/v1 diff --git a/examples/postgrescluster/postgrescluster.yaml b/examples/postgrescluster/postgrescluster.yaml index 7ad4524571..75756af94e 100644 --- a/examples/postgrescluster/postgrescluster.yaml +++ b/examples/postgrescluster/postgrescluster.yaml @@ -3,7 +3,6 @@ kind: PostgresCluster metadata: name: hippo spec: - image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.3-1 postgresVersion: 16 instances: - name: instance1 @@ -15,7 +14,6 @@ spec: storage: 1Gi backups: pgbackrest: - image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.51-1 repos: - name: repo1 volume: @@ -34,5 +32,4 @@ spec: requests: storage: 1Gi proxy: - pgBouncer: - image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:ubi8-1.22-1 + pgBouncer: {} diff --git a/go.mod b/go.mod index 7cded9e9ff..41160a9f30 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,7 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect + golang.org/x/mod v0.24.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect ) @@ -122,7 +123,7 @@ require ( golang.org/x/term v0.31.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.31.0 // indirect + golang.org/x/tools v0.31.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250311190419-81fb87f6b8bf // indirect diff --git a/go.sum b/go.sum index e007b48be3..b5ff838d97 100644 --- a/go.sum +++ b/go.sum @@ -287,6 +287,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/internal/controller/pgupgrade/jobs.go b/internal/controller/pgupgrade/jobs.go index 3194fbfc1c..bab9d49637 100644 --- a/internal/controller/pgupgrade/jobs.go +++ b/internal/controller/pgupgrade/jobs.go @@ -12,10 +12,13 @@ import ( appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/internal/naming" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -32,9 +35,9 @@ func pgUpgradeJob(upgrade *v1beta1.PGUpgrade) metav1.ObjectMeta { // upgradeCommand returns an entrypoint that prepares the filesystem for // and performs a PostgreSQL major version upgrade using pg_upgrade. -func upgradeCommand(upgrade *v1beta1.PGUpgrade, fetchKeyCommand string) []string { - oldVersion := fmt.Sprint(upgrade.Spec.FromPostgresVersion) - newVersion := fmt.Sprint(upgrade.Spec.ToPostgresVersion) +func upgradeCommand(oldVersion, newVersion int, fetchKeyCommand string, availableCPUs int) []string { + // Use multiple CPUs when three or more are available. + argJobs := fmt.Sprintf(` --jobs=%d`, max(1, availableCPUs-1)) // if the fetch key command is set for TDE, provide the value during initialization initdb := `/usr/pgsql-"${new_version}"/bin/initdb -k -D /pgdata/pg"${new_version}"` @@ -42,7 +45,7 @@ func upgradeCommand(upgrade *v1beta1.PGUpgrade, fetchKeyCommand string) []string initdb += ` --encryption-key-command "` + fetchKeyCommand + `"` } - args := []string{oldVersion, newVersion} + args := []string{fmt.Sprint(oldVersion), fmt.Sprint(newVersion)} script := strings.Join([]string{ `declare -r data_volume='/pgdata' old_version="$1" new_version="$2"`, `printf 'Performing PostgreSQL upgrade from version "%s" to "%s" ...\n\n' "$@"`, @@ -96,14 +99,14 @@ func upgradeCommand(upgrade *v1beta1.PGUpgrade, fetchKeyCommand string) []string `echo -e "Step 5: Running pg_upgrade check...\n"`, `time /usr/pgsql-"${new_version}"/bin/pg_upgrade --old-bindir /usr/pgsql-"${old_version}"/bin \`, `--new-bindir /usr/pgsql-"${new_version}"/bin --old-datadir /pgdata/pg"${old_version}"\`, - ` --new-datadir /pgdata/pg"${new_version}" --link --check`, + ` --new-datadir /pgdata/pg"${new_version}" --link --check` + argJobs, // Assuming the check completes successfully, the pg_upgrade command will // be run that actually prepares the upgraded pgdata directory. `echo -e "\nStep 6: Running pg_upgrade...\n"`, `time /usr/pgsql-"${new_version}"/bin/pg_upgrade --old-bindir /usr/pgsql-"${old_version}"/bin \`, `--new-bindir /usr/pgsql-"${new_version}"/bin --old-datadir /pgdata/pg"${old_version}" \`, - `--new-datadir /pgdata/pg"${new_version}" --link`, + `--new-datadir /pgdata/pg"${new_version}" --link` + argJobs, // Since we have cleared the Patroni cluster step by removing the EndPoints, we copy patroni.dynamic.json // from the old data dir to help retain PostgreSQL parameters you had set before. @@ -117,10 +120,21 @@ func upgradeCommand(upgrade *v1beta1.PGUpgrade, fetchKeyCommand string) []string return append([]string{"bash", "-ceu", "--", script, "upgrade"}, args...) } +// largestWholeCPU returns the maximum CPU request or limit as a non-negative +// integer of CPUs. When resources lacks any CPU, the result is zero. +func largestWholeCPU(resources corev1.ResourceRequirements) int { + // Read CPU quantities as millicores then divide to get the "floor." + // NOTE: [resource.Quantity.Value] looks easier, but it rounds up. + return max( + int(resources.Limits.Cpu().ScaledValue(resource.Milli)/1000), + int(resources.Requests.Cpu().ScaledValue(resource.Milli)/1000), + 0) +} + // generateUpgradeJob returns a Job that can upgrade the PostgreSQL data // directory of the startup instance. func (r *PGUpgradeReconciler) generateUpgradeJob( - _ context.Context, upgrade *v1beta1.PGUpgrade, + ctx context.Context, upgrade *v1beta1.PGUpgrade, startup *appsv1.StatefulSet, fetchKeyCommand string, ) *batchv1.Job { job := &batchv1.Job{} @@ -129,7 +143,6 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( job.Namespace = upgrade.Namespace job.Name = pgUpgradeJob(upgrade).Name - job.Annotations = upgrade.Spec.Metadata.GetAnnotationsOrNil() job.Labels = Merge(upgrade.Spec.Metadata.GetLabelsOrNil(), commonLabels(pgUpgrade, upgrade), //FIXME role pgupgrade map[string]string{ @@ -145,6 +158,11 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( } } + job.Annotations = Merge(upgrade.Spec.Metadata.GetAnnotationsOrNil(), + map[string]string{ + naming.DefaultContainerAnnotation: database.Name, + }) + // Copy the pod template from the startup instance StatefulSet. This includes // the service account, volumes, DNS policies, and scheduling constraints. startup.Spec.Template.DeepCopyInto(&job.Spec.Template) @@ -162,6 +180,12 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( job.Spec.BackoffLimit = initialize.Int32(0) job.Spec.Template.Spec.RestartPolicy = corev1.RestartPolicyNever + // When enabled, calculate the number of CPUs for pg_upgrade. + wholeCPUs := 0 + if feature.Enabled(ctx, feature.PGUpgradeCPUConcurrency) { + wholeCPUs = largestWholeCPU(upgrade.Spec.Resources) + } + // Replace all containers with one that does the upgrade. job.Spec.Template.Spec.EphemeralContainers = nil @@ -180,7 +204,11 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( VolumeMounts: volumeMounts, // K8SPG-254 // Use our upgrade command and the specified image and resources. - Command: upgradeCommand(upgrade, fetchKeyCommand), + Command: upgradeCommand( + upgrade.Spec.FromPostgresVersion, + upgrade.Spec.ToPostgresVersion, + fetchKeyCommand, + wholeCPUs), Image: pgUpgradeContainerImage(upgrade), ImagePullPolicy: upgrade.Spec.ImagePullPolicy, Resources: upgrade.Spec.Resources, @@ -247,7 +275,6 @@ func (r *PGUpgradeReconciler) generateRemoveDataJob( job.Namespace = upgrade.Namespace job.Name = upgrade.Name + "-" + sts.Name - job.Annotations = upgrade.Spec.Metadata.GetAnnotationsOrNil() job.Labels = labels.Merge(upgrade.Spec.Metadata.GetLabelsOrNil(), commonLabels(removeData, upgrade)) //FIXME role removedata @@ -260,6 +287,11 @@ func (r *PGUpgradeReconciler) generateRemoveDataJob( } } + job.Annotations = Merge(upgrade.Spec.Metadata.GetAnnotationsOrNil(), + map[string]string{ + naming.DefaultContainerAnnotation: database.Name, + }) + // Copy the pod template from the sts instance StatefulSet. This includes // the service account, volumes, DNS policies, and scheduling constraints. sts.Spec.Template.DeepCopyInto(&job.Spec.Template) diff --git a/internal/controller/pgupgrade/jobs_test.go b/internal/controller/pgupgrade/jobs_test.go index 077bf55963..eb3a45d414 100644 --- a/internal/controller/pgupgrade/jobs_test.go +++ b/internal/controller/pgupgrade/jobs_test.go @@ -16,11 +16,85 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "sigs.k8s.io/yaml" + "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/internal/testing/cmp" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) +func TestLargestWholeCPU(t *testing.T) { + assert.Equal(t, 0, + largestWholeCPU(corev1.ResourceRequirements{}), + "expected the zero value to be zero") + + for _, tt := range []struct { + Name, ResourcesYAML string + Result int + }{ + { + Name: "Negatives", ResourcesYAML: `{requests: {cpu: -3}, limits: {cpu: -5}}`, + Result: 0, + }, + { + Name: "SmallPositive", ResourcesYAML: `limits: {cpu: 600m}`, + Result: 0, + }, + { + Name: "FractionalPositive", ResourcesYAML: `requests: {cpu: 2200m}`, + Result: 2, + }, + { + Name: "LargePositive", ResourcesYAML: `limits: {cpu: 10}`, + Result: 10, + }, + { + Name: "RequestsAndLimits", ResourcesYAML: `{requests: {cpu: 2}, limits: {cpu: 4}}`, + Result: 4, + }, + } { + t.Run(tt.Name, func(t *testing.T) { + var resources corev1.ResourceRequirements + assert.NilError(t, yaml.Unmarshal([]byte(tt.ResourcesYAML), &resources)) + assert.Equal(t, tt.Result, largestWholeCPU(resources)) + }) + } +} + +func TestUpgradeCommand(t *testing.T) { + expectScript := func(t *testing.T, script string) { + t.Helper() + + t.Run("PrettyYAML", func(t *testing.T) { + b, err := yaml.Marshal(script) + assert.NilError(t, err) + assert.Assert(t, strings.HasPrefix(string(b), `|`), + "expected literal block scalar, got:\n%s", b) + }) + } + + t.Run("CPUs", func(t *testing.T) { + for _, tt := range []struct { + CPUs int + Jobs string + }{ + {CPUs: 0, Jobs: "--jobs=1"}, + {CPUs: 1, Jobs: "--jobs=1"}, + {CPUs: 2, Jobs: "--jobs=1"}, + {CPUs: 3, Jobs: "--jobs=2"}, + {CPUs: 10, Jobs: "--jobs=9"}, + } { + command := upgradeCommand(10, 11, "", tt.CPUs) + assert.Assert(t, len(command) > 3) + assert.DeepEqual(t, []string{"bash", "-ceu", "--"}, command[:3]) + + script := command[3] + assert.Assert(t, cmp.Contains(script, tt.Jobs)) + + expectScript(t, script) + } + }) +} + func TestGenerateUpgradeJob(t *testing.T) { ctx := context.Background() reconciler := &PGUpgradeReconciler{} @@ -62,6 +136,8 @@ func TestGenerateUpgradeJob(t *testing.T) { apiVersion: batch/v1 kind: Job metadata: + annotations: + kubectl.kubernetes.io/default-container: database creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 @@ -81,6 +157,8 @@ spec: backoffLimit: 0 template: metadata: + annotations: + kubectl.kubernetes.io/default-container: database creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 @@ -116,11 +194,11 @@ spec: echo -e "Step 5: Running pg_upgrade check...\n" time /usr/pgsql-"${new_version}"/bin/pg_upgrade --old-bindir /usr/pgsql-"${old_version}"/bin \ --new-bindir /usr/pgsql-"${new_version}"/bin --old-datadir /pgdata/pg"${old_version}"\ - --new-datadir /pgdata/pg"${new_version}" --link --check + --new-datadir /pgdata/pg"${new_version}" --link --check --jobs=1 echo -e "\nStep 6: Running pg_upgrade...\n" time /usr/pgsql-"${new_version}"/bin/pg_upgrade --old-bindir /usr/pgsql-"${old_version}"/bin \ --new-bindir /usr/pgsql-"${new_version}"/bin --old-datadir /pgdata/pg"${old_version}" \ - --new-datadir /pgdata/pg"${new_version}" --link + --new-datadir /pgdata/pg"${new_version}" --link --jobs=1 echo -e "\nStep 7: Copying patroni.dynamic.json...\n" cp /pgdata/pg"${old_version}"/patroni.dynamic.json /pgdata/pg"${new_version}" echo -e "\npg_upgrade Job Complete!" @@ -145,9 +223,19 @@ spec: status: {} `)) + t.Run(feature.PGUpgradeCPUConcurrency+"Enabled", func(t *testing.T) { + gate := feature.NewGate() + assert.NilError(t, gate.SetFromMap(map[string]bool{ + feature.PGUpgradeCPUConcurrency: true, + })) + ctx := feature.NewContext(context.Background(), gate) + + job := reconciler.generateUpgradeJob(ctx, upgrade, startup, "") + assert.Assert(t, cmp.MarshalContains(job, `--jobs=2`)) + }) + tdeJob := reconciler.generateUpgradeJob(ctx, upgrade, startup, "echo testKey") - b, _ := yaml.Marshal(tdeJob) - assert.Assert(t, strings.Contains(string(b), + assert.Assert(t, cmp.MarshalContains(tdeJob, `/usr/pgsql-"${new_version}"/bin/initdb -k -D /pgdata/pg"${new_version}" --encryption-key-command "echo testKey"`)) } @@ -193,6 +281,8 @@ func TestGenerateRemoveDataJob(t *testing.T) { apiVersion: batch/v1 kind: Job metadata: + annotations: + kubectl.kubernetes.io/default-container: database creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 @@ -211,6 +301,8 @@ spec: backoffLimit: 0 template: metadata: + annotations: + kubectl.kubernetes.io/default-container: database creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 diff --git a/internal/controller/pgupgrade/world_test.go b/internal/controller/pgupgrade/world_test.go index f73e8b319f..71ec5e5828 100644 --- a/internal/controller/pgupgrade/world_test.go +++ b/internal/controller/pgupgrade/world_test.go @@ -13,8 +13,8 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" + "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -34,7 +34,7 @@ func TestPopulateCluster(t *testing.T) { t.Run("NotFound", func(t *testing.T) { cluster := v1beta1.NewPostgresCluster() - expected := apierrors.NewNotFound(schema.GroupResource{}, "name") + expected := apierrors.NewNotFound(runtime.GR{}, "name") world := NewWorld() err := world.populateCluster(cluster, expected) diff --git a/internal/controller/postgrescluster/cluster_test.go b/internal/controller/postgrescluster/cluster_test.go index 7f27d424b9..dbfd7de93b 100644 --- a/internal/controller/postgrescluster/cluster_test.go +++ b/internal/controller/postgrescluster/cluster_test.go @@ -8,7 +8,6 @@ import ( "context" "testing" - "github.com/pkg/errors" "go.opentelemetry.io/otel" "gotest.tools/v3/assert" appsv1 "k8s.io/api/apps/v1" @@ -17,12 +16,11 @@ import ( rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" + "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/internal/naming" "github.com/percona/percona-postgresql-operator/internal/testing/cmp" @@ -30,7 +28,7 @@ import ( "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) -var gvks = []schema.GroupVersionKind{{ +var gvks = []runtime.GVK{{ Group: corev1.SchemeGroupVersion.Group, Version: corev1.SchemeGroupVersion.Version, Kind: "ConfigMapList", @@ -91,7 +89,7 @@ func TestCustomLabels(t *testing.T) { ns := setupNamespace(t, cc) reconcileTestCluster := func(cluster *v1beta1.PostgresCluster) { - assert.NilError(t, errors.WithStack(reconciler.Client.Create(ctx, cluster))) + assert.NilError(t, reconciler.Client.Create(ctx, cluster)) t.Cleanup(func() { // Remove finalizers, if any, so the namespace can terminate. assert.Check(t, client.IgnoreNotFound( @@ -107,28 +105,25 @@ func TestCustomLabels(t *testing.T) { assert.Assert(t, result.Requeue == false) } - getUnstructuredLabels := func(cluster v1beta1.PostgresCluster, u unstructured.Unstructured) (map[string]map[string]string, error) { - var err error + getUnstructuredLabels := func(t *testing.T, cluster *v1beta1.PostgresCluster, u *unstructured.Unstructured) map[string]map[string]string { + t.Helper() labels := map[string]map[string]string{} - if metav1.IsControlledBy(&u, &cluster) { + if metav1.IsControlledBy(u, cluster) { switch u.GetKind() { case "StatefulSet": - var resource appsv1.StatefulSet - err = runtime.DefaultUnstructuredConverter. - FromUnstructured(u.UnstructuredContent(), &resource) + resource, err := runtime.FromUnstructuredObject[appsv1.StatefulSet](u) + assert.NilError(t, err) labels["resource"] = resource.GetLabels() labels["podTemplate"] = resource.Spec.Template.GetLabels() case "Deployment": - var resource appsv1.Deployment - err = runtime.DefaultUnstructuredConverter. - FromUnstructured(u.UnstructuredContent(), &resource) + resource, err := runtime.FromUnstructuredObject[appsv1.Deployment](u) + assert.NilError(t, err) labels["resource"] = resource.GetLabels() labels["podTemplate"] = resource.Spec.Template.GetLabels() case "CronJob": - var resource batchv1.CronJob - err = runtime.DefaultUnstructuredConverter. - FromUnstructured(u.UnstructuredContent(), &resource) + resource, err := runtime.FromUnstructuredObject[batchv1.CronJob](u) + assert.NilError(t, err) labels["resource"] = resource.GetLabels() labels["jobTemplate"] = resource.Spec.JobTemplate.GetLabels() labels["jobPodTemplate"] = resource.Spec.JobTemplate.Spec.Template.GetLabels() @@ -136,7 +131,7 @@ func TestCustomLabels(t *testing.T) { labels["resource"] = u.GetLabels() } } - return labels, err + return labels } t.Run("Cluster", func(t *testing.T) { @@ -182,10 +177,8 @@ func TestCustomLabels(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - labels, err := getUnstructuredLabels(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + labels := getUnstructuredLabels(t, cluster, &u) for resourceType, resourceLabels := range labels { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceLabels["my.cluster.label"], "daisy") @@ -238,11 +231,8 @@ func TestCustomLabels(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - - labels, err := getUnstructuredLabels(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + labels := getUnstructuredLabels(t, cluster, &u) for resourceType, resourceLabels := range labels { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceLabels["my.instance.label"], set.Metadata.Labels["my.instance.label"]) @@ -287,11 +277,8 @@ func TestCustomLabels(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - - labels, err := getUnstructuredLabels(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + labels := getUnstructuredLabels(t, cluster, &u) for resourceType, resourceLabels := range labels { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceLabels["my.pgbackrest.label"], "lucy") @@ -325,11 +312,8 @@ func TestCustomLabels(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - - labels, err := getUnstructuredLabels(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + labels := getUnstructuredLabels(t, cluster, &u) for resourceType, resourceLabels := range labels { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceLabels["my.pgbouncer.label"], "lucy") @@ -355,7 +339,7 @@ func TestCustomAnnotations(t *testing.T) { ns := setupNamespace(t, cc) reconcileTestCluster := func(cluster *v1beta1.PostgresCluster) { - assert.NilError(t, errors.WithStack(reconciler.Client.Create(ctx, cluster))) + assert.NilError(t, reconciler.Client.Create(ctx, cluster)) t.Cleanup(func() { // Remove finalizers, if any, so the namespace can terminate. assert.Check(t, client.IgnoreNotFound( @@ -371,28 +355,25 @@ func TestCustomAnnotations(t *testing.T) { assert.Assert(t, result.Requeue == false) } - getUnstructuredAnnotations := func(cluster v1beta1.PostgresCluster, u unstructured.Unstructured) (map[string]map[string]string, error) { - var err error + getUnstructuredAnnotations := func(t *testing.T, cluster *v1beta1.PostgresCluster, u *unstructured.Unstructured) map[string]map[string]string { + t.Helper() annotations := map[string]map[string]string{} - if metav1.IsControlledBy(&u, &cluster) { + if metav1.IsControlledBy(u, cluster) { switch u.GetKind() { case "StatefulSet": - var resource appsv1.StatefulSet - err = runtime.DefaultUnstructuredConverter. - FromUnstructured(u.UnstructuredContent(), &resource) + resource, err := runtime.FromUnstructuredObject[appsv1.StatefulSet](u) + assert.NilError(t, err) annotations["resource"] = resource.GetAnnotations() annotations["podTemplate"] = resource.Spec.Template.GetAnnotations() case "Deployment": - var resource appsv1.Deployment - err = runtime.DefaultUnstructuredConverter. - FromUnstructured(u.UnstructuredContent(), &resource) + resource, err := runtime.FromUnstructuredObject[appsv1.Deployment](u) + assert.NilError(t, err) annotations["resource"] = resource.GetAnnotations() annotations["podTemplate"] = resource.Spec.Template.GetAnnotations() case "CronJob": - var resource batchv1.CronJob - err = runtime.DefaultUnstructuredConverter. - FromUnstructured(u.UnstructuredContent(), &resource) + resource, err := runtime.FromUnstructuredObject[batchv1.CronJob](u) + assert.NilError(t, err) annotations["resource"] = resource.GetAnnotations() annotations["jobTemplate"] = resource.Spec.JobTemplate.GetAnnotations() annotations["jobPodTemplate"] = resource.Spec.JobTemplate.Spec.Template.GetAnnotations() @@ -400,7 +381,7 @@ func TestCustomAnnotations(t *testing.T) { annotations["resource"] = u.GetAnnotations() } } - return annotations, err + return annotations } t.Run("Cluster", func(t *testing.T) { @@ -447,10 +428,8 @@ func TestCustomAnnotations(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - annotations, err := getUnstructuredAnnotations(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + annotations := getUnstructuredAnnotations(t, cluster, &u) for resourceType, resourceAnnotations := range annotations { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceAnnotations["my.cluster.annotation"], "daisy") @@ -503,11 +482,8 @@ func TestCustomAnnotations(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - - annotations, err := getUnstructuredAnnotations(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + annotations := getUnstructuredAnnotations(t, cluster, &u) for resourceType, resourceAnnotations := range annotations { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceAnnotations["my.instance.annotation"], set.Metadata.Annotations["my.instance.annotation"]) @@ -552,11 +528,8 @@ func TestCustomAnnotations(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - - annotations, err := getUnstructuredAnnotations(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + annotations := getUnstructuredAnnotations(t, cluster, &u) for resourceType, resourceAnnotations := range annotations { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceAnnotations["my.pgbackrest.annotation"], "lucy") @@ -590,11 +563,8 @@ func TestCustomAnnotations(t *testing.T) { client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selector})) - for i := range uList.Items { - u := uList.Items[i] - - annotations, err := getUnstructuredAnnotations(*cluster, u) - assert.NilError(t, err) + for _, u := range uList.Items { + annotations := getUnstructuredAnnotations(t, cluster, &u) for resourceType, resourceAnnotations := range annotations { t.Run(u.GetKind()+"/"+u.GetName()+"/"+resourceType, func(t *testing.T) { assert.Equal(t, resourceAnnotations["my.pgbouncer.annotation"], "lucy") diff --git a/internal/controller/postgrescluster/controller.go b/internal/controller/postgrescluster/controller.go index 72ce2186f0..12b806b5e0 100644 --- a/internal/controller/postgrescluster/controller.go +++ b/internal/controller/postgrescluster/controller.go @@ -142,6 +142,16 @@ func (r *Reconciler) Reconcile( return runtime.ErrorWithBackoff(err) } } + // Issue Warning Event if postgres version is EOL according to PostgreSQL: + // https://www.postgresql.org/support/versioning/ + currentTime := time.Now() + if postgres.ReleaseIsFinal(cluster.Spec.PostgresVersion, currentTime) { + r.Recorder.Eventf(cluster, corev1.EventTypeWarning, "EndOfLifePostgresVersion", + "The last minor version of Postgres %[1]v has been released."+ + " PG %[1]v will no longer receive updates. We recommend upgrading."+ + " See https://www.postgresql.org/support/versioning", + cluster.Spec.PostgresVersion) + } if cluster.Spec.Standby != nil && cluster.Spec.Standby.Enabled && diff --git a/internal/controller/postgrescluster/controller_test.go b/internal/controller/postgrescluster/controller_test.go index 17c56eb3d5..2bd0bef761 100644 --- a/internal/controller/postgrescluster/controller_test.go +++ b/internal/controller/postgrescluster/controller_test.go @@ -13,7 +13,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" - "github.com/pkg/errors" + "github.com/pkg/errors" //nolint:depguard // This legacy test covers so much code, it logs the origin of unexpected errors. "go.opentelemetry.io/otel" "gotest.tools/v3/assert" @@ -587,4 +587,68 @@ spec: Expect(instance.Spec.Replicas).To(PointTo(BeEquivalentTo(1))) }) }) + + Context("Postgres version EOL", func() { + var cluster *v1beta1.PostgresCluster + + BeforeEach(func() { + cluster = create(` +metadata: + name: old-postgres +spec: + postgresVersion: 12 + image: postgres + instances: + - name: instance1 + initContainer: + image: pg-operator + dataVolumeClaimSpec: + accessModes: + - "ReadWriteMany" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: pgbackrest + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi +`) + Expect(reconcile(cluster)).To(BeZero()) + }) + + AfterEach(func() { + ctx := context.Background() + + if cluster != nil { + Expect(client.IgnoreNotFound( + suite.Client.Delete(ctx, cluster), + )).To(Succeed()) + + // Remove finalizers, if any, so the namespace can terminate. + Expect(client.IgnoreNotFound( + suite.Client.Patch(ctx, cluster, client.RawPatch( + client.Merge.Type(), []byte(`{"metadata":{"finalizers":[]}}`))), + )).To(Succeed()) + } + }) + + Specify("Postgres EOL Warning Event", func() { + existing := &v1beta1.PostgresCluster{} + Expect(suite.Client.Get( + context.Background(), client.ObjectKeyFromObject(cluster), existing, + )).To(Succeed()) + + event, ok := <-test.Recorder.Events + Expect(ok).To(BeTrue()) + Expect(event).To(ContainSubstring("PG 12 will no longer receive updates. We recommend upgrading.")) + }) + }) }) diff --git a/internal/controller/postgrescluster/instance.go b/internal/controller/postgrescluster/instance.go index 6c60b92843..b1e3cc39be 100644 --- a/internal/controller/postgrescluster/instance.go +++ b/internal/controller/postgrescluster/instance.go @@ -21,7 +21,6 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/controller-runtime/pkg/client" @@ -471,7 +470,7 @@ func (r *Reconciler) deleteInstances( // stop schedules pod for deletion by scaling its controller to zero. stop := func(pod *corev1.Pod) error { - instance := &unstructured.Unstructured{} + instance := &appsv1.StatefulSet{} instance.SetNamespace(cluster.Namespace) switch owner := metav1.GetControllerOfNoCopy(pod); { @@ -479,8 +478,6 @@ func (r *Reconciler) deleteInstances( return errors.Errorf("pod %q has no owner", client.ObjectKeyFromObject(pod)) case owner.Kind == "StatefulSet": - instance.SetAPIVersion(owner.APIVersion) - instance.SetKind(owner.Kind) instance.SetName(owner.Name) default: @@ -540,7 +537,7 @@ func (r *Reconciler) deleteInstance( cluster *v1beta1.PostgresCluster, instanceName string, ) error { - gvks := []schema.GroupVersionKind{{ + gvks := []runtime.GVK{{ Group: corev1.SchemeGroupVersion.Group, Version: corev1.SchemeGroupVersion.Version, Kind: "ConfigMapList", @@ -1287,6 +1284,15 @@ func generateInstanceStatefulSetIntent(_ context.Context, cluster.Spec.Metadata.GetAnnotationsOrNil(), spec.Metadata.GetAnnotationsOrNil(), ) + if cluster.CompareVersion("2.7.0") >= 0 { + sts.Spec.Template.Annotations = naming.Merge( + cluster.Spec.Metadata.GetAnnotationsOrNil(), + spec.Metadata.GetAnnotationsOrNil(), + map[string]string{ + naming.DefaultContainerAnnotation: naming.ContainerDatabase, + }, + ) + } sts.Spec.Template.Labels = naming.Merge( cluster.Spec.Metadata.GetLabelsOrNil(), spec.Metadata.GetLabelsOrNil(), diff --git a/internal/controller/postgrescluster/instance_test.go b/internal/controller/postgrescluster/instance_test.go index c4067ad303..17799ee6fb 100644 --- a/internal/controller/postgrescluster/instance_test.go +++ b/internal/controller/postgrescluster/instance_test.go @@ -6,6 +6,7 @@ package postgrescluster import ( "context" + "errors" "fmt" "os" "sort" @@ -15,7 +16,6 @@ import ( "github.com/go-logr/logr/funcr" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/pkg/errors" "go.opentelemetry.io/otel" "gotest.tools/v3/assert" appsv1 "k8s.io/api/apps/v1" @@ -1351,7 +1351,7 @@ func TestDeleteInstance(t *testing.T) { cluster := testCluster() cluster.Namespace = setupNamespace(t, cc).Name - assert.NilError(t, errors.WithStack(reconciler.Client.Create(ctx, cluster))) + assert.NilError(t, reconciler.Client.Create(ctx, cluster)) t.Cleanup(func() { // Remove finalizers, if any, so the namespace can terminate. assert.Check(t, client.IgnoreNotFound( @@ -1405,9 +1405,9 @@ func TestDeleteInstance(t *testing.T) { err := wait.PollUntilContextTimeout(ctx, time.Second*3, Scale(time.Second*30), false, func(ctx context.Context) (bool, error) { uList := &unstructured.UnstructuredList{} uList.SetGroupVersionKind(gvk) - assert.NilError(t, errors.WithStack(reconciler.Client.List(ctx, uList, + assert.NilError(t, reconciler.Client.List(ctx, uList, client.InNamespace(cluster.Namespace), - client.MatchingLabelsSelector{Selector: selector}))) + client.MatchingLabelsSelector{Selector: selector})) if len(uList.Items) == 0 { return true, nil diff --git a/internal/controller/postgrescluster/patroni_test.go b/internal/controller/postgrescluster/patroni_test.go index 3351b199b3..b887d8c3b5 100644 --- a/internal/controller/postgrescluster/patroni_test.go +++ b/internal/controller/postgrescluster/patroni_test.go @@ -6,6 +6,7 @@ package postgrescluster import ( "context" + "errors" "fmt" "io" "os" @@ -14,7 +15,6 @@ import ( "testing" "time" - "github.com/pkg/errors" "gotest.tools/v3/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -550,17 +550,17 @@ func TestReconcilePatroniSwitchover(t *testing.T) { switch { case timelineCall: timelineCall = false - stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-67mc-0", "Host": "hippo-instance1-67mc-0.hippo-pods", "Role": "Leader", "State": "running", "TL": 4}, {"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) + _, _ = stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-67mc-0", "Host": "hippo-instance1-67mc-0.hippo-pods", "Role": "Leader", "State": "running", "TL": 4}, {"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) case timelineCallNoLeader: - stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) + _, _ = stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) case callError: return errors.New("boom") case callFails: - stdout.Write([]byte("bang")) + _, _ = stdout.Write([]byte("bang")) case failover: - stdout.Write([]byte("failed over")) + _, _ = stdout.Write([]byte("failed over")) default: - stdout.Write([]byte("switched over")) + _, _ = stdout.Write([]byte("switched over")) } return nil }, diff --git a/internal/controller/postgrescluster/pgadmin.go b/internal/controller/postgrescluster/pgadmin.go index d4e16767f4..091b894788 100644 --- a/internal/controller/postgrescluster/pgadmin.go +++ b/internal/controller/postgrescluster/pgadmin.go @@ -261,7 +261,11 @@ func (r *Reconciler) reconcilePGAdminStatefulSet( } sts.Spec.Template.Annotations = naming.Merge( cluster.Spec.Metadata.GetAnnotationsOrNil(), - cluster.Spec.UserInterface.PGAdmin.Metadata.GetAnnotationsOrNil()) + cluster.Spec.UserInterface.PGAdmin.Metadata.GetAnnotationsOrNil(), + map[string]string{ + naming.DefaultContainerAnnotation: naming.ContainerPGAdmin, + }, + ) sts.Spec.Template.Labels = naming.Merge( cluster.Spec.Metadata.GetLabelsOrNil(), cluster.Spec.UserInterface.PGAdmin.Metadata.GetLabelsOrNil(), diff --git a/internal/controller/postgrescluster/pgadmin_test.go b/internal/controller/postgrescluster/pgadmin_test.go index a52752c5c3..c1bead1f04 100644 --- a/internal/controller/postgrescluster/pgadmin_test.go +++ b/internal/controller/postgrescluster/pgadmin_test.go @@ -6,11 +6,11 @@ package postgrescluster import ( "context" + "errors" "io" "strconv" "testing" - "github.com/pkg/errors" "gotest.tools/v3/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -520,6 +520,8 @@ func TestReconcilePGAdminStatefulSet(t *testing.T) { template.Spec.Volumes = nil assert.Assert(t, cmp.MarshalMatches(template.ObjectMeta, ` +annotations: + kubectl.kubernetes.io/default-container: pgadmin creationTimestamp: null labels: app.kubernetes.io/instance: test-cluster @@ -640,6 +642,7 @@ terminationGracePeriodSeconds: 30 assert.Assert(t, cmp.MarshalMatches(template.ObjectMeta, ` annotations: annotation1: annotationvalue + kubectl.kubernetes.io/default-container: pgadmin creationTimestamp: null labels: app.kubernetes.io/instance: custom-cluster diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index fc6ffc169e..89778331ab 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -24,15 +24,12 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/percona/percona-postgresql-operator/internal/config" + "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/internal/logging" @@ -212,7 +209,7 @@ func (r *Reconciler) getPGBackRestResources(ctx context.Context, repoResources := &RepoResources{} - gvks := []schema.GroupVersionKind{{ + gvks := []runtime.GVK{{ Group: appsv1.SchemeGroupVersion.Group, Version: appsv1.SchemeGroupVersion.Version, Kind: "StatefulSetList", @@ -444,27 +441,24 @@ func unstructuredToRepoResources(kind string, repoResources *RepoResources, switch kind { case "StatefulSetList": - var stsList appsv1.StatefulSetList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &stsList); err != nil { + stsList, err := runtime.FromUnstructuredList[appsv1.StatefulSetList](uList) + if err != nil { return errors.WithStack(err) } for i := range stsList.Items { repoResources.hosts = append(repoResources.hosts, &stsList.Items[i]) } case "CronJobList": - var cronList batchv1.CronJobList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &cronList); err != nil { + cronList, err := runtime.FromUnstructuredList[batchv1.CronJobList](uList) + if err != nil { return errors.WithStack(err) } for i := range cronList.Items { repoResources.cronjobs = append(repoResources.cronjobs, &cronList.Items[i]) } case "JobList": - var jobList batchv1.JobList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &jobList); err != nil { + jobList, err := runtime.FromUnstructuredList[batchv1.JobList](uList) + if err != nil { return errors.WithStack(err) } // we care about replica create backup jobs and manual backup jobs @@ -482,9 +476,8 @@ func unstructuredToRepoResources(kind string, repoResources *RepoResources, // Repository host now uses mTLS for encryption, authentication, and authorization. // Configmaps for SSHD are no longer managed here. case "PersistentVolumeClaimList": - var pvcList corev1.PersistentVolumeClaimList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &pvcList); err != nil { + pvcList, err := runtime.FromUnstructuredList[corev1.PersistentVolumeClaimList](uList) + if err != nil { return errors.WithStack(err) } for i := range pvcList.Items { @@ -496,27 +489,24 @@ func unstructuredToRepoResources(kind string, repoResources *RepoResources, // TODO(tjmoore4): Consider adding all pgBackRest secrets to RepoResources to // observe all pgBackRest secrets in one place. case "ServiceAccountList": - var saList corev1.ServiceAccountList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &saList); err != nil { + saList, err := runtime.FromUnstructuredList[corev1.ServiceAccountList](uList) + if err != nil { return errors.WithStack(err) } for i := range saList.Items { repoResources.sas = append(repoResources.sas, &saList.Items[i]) } case "RoleList": - var roleList rbacv1.RoleList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &roleList); err != nil { + roleList, err := runtime.FromUnstructuredList[rbacv1.RoleList](uList) + if err != nil { return errors.WithStack(err) } for i := range roleList.Items { repoResources.roles = append(repoResources.roles, &roleList.Items[i]) } case "RoleBindingList": - var rb rbacv1.RoleBindingList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &rb); err != nil { + rb, err := runtime.FromUnstructuredList[rbacv1.RoleBindingList](uList) + if err != nil { return errors.WithStack(err) } for i := range rb.Items { @@ -537,9 +527,8 @@ func (r *Reconciler) setScheduledJobStatus(ctx context.Context, log := logging.FromContext(ctx) uList := &unstructured.UnstructuredList{Items: items} - var jobList batchv1.JobList - if err := runtime.DefaultUnstructuredConverter. - FromUnstructured(uList.UnstructuredContent(), &jobList); err != nil { + jobList, err := runtime.FromUnstructuredList[batchv1.JobList](uList) + if err != nil { // as this is only setting a status that is not otherwise used // by the Operator, simply log an error and return rather than // bubble this up to the other functions @@ -554,8 +543,9 @@ func (r *Reconciler) setScheduledJobStatus(ctx context.Context, for _, job := range jobList.Items { // we only care about the scheduled backup Jobs created by the // associated CronJobs - sbs := v1beta1.PGBackRestScheduledBackupStatus{} if job.GetLabels()[naming.LabelPGBackRestCronJob] != "" { + sbs := v1beta1.PGBackRestScheduledBackupStatus{} + if len(job.OwnerReferences) > 0 { sbs.CronJobName = job.OwnerReferences[0].Name } @@ -587,7 +577,17 @@ func (r *Reconciler) generateRepoHostIntent(ctx context.Context, postgresCluster annotations := naming.Merge( postgresCluster.Spec.Metadata.GetAnnotationsOrNil(), - postgresCluster.Spec.Backups.PGBackRest.Metadata.GetAnnotationsOrNil()) + postgresCluster.Spec.Backups.PGBackRest.Metadata.GetAnnotationsOrNil(), + ) + if postgresCluster.CompareVersion("2.7.0") >= 0 { + annotations = naming.Merge( + postgresCluster.Spec.Metadata.GetAnnotationsOrNil(), + postgresCluster.Spec.Backups.PGBackRest.Metadata.GetAnnotationsOrNil(), + map[string]string{ + naming.DefaultContainerAnnotation: naming.PGBackRestRepoContainerName, + }, + ) + } labels := naming.Merge( postgresCluster.Spec.Metadata.GetLabelsOrNil(), postgresCluster.Spec.Backups.PGBackRest.Metadata.GetLabelsOrNil(), @@ -737,8 +737,7 @@ func (r *Reconciler) generateRepoHostIntent(ctx context.Context, postgresCluster addTMPEmptyDir(&repo.Spec.Template, sizeLimit) // set ownership references - if err := controllerutil.SetControllerReference(postgresCluster, repo, - r.Client.Scheme()); err != nil { + if err := r.setControllerReference(postgresCluster, repo); err != nil { return nil, err } @@ -861,6 +860,16 @@ func generateBackupJobSpecIntent(ctx context.Context, postgresCluster *v1beta1.P } } + if postgresCluster.CompareVersion("2.7.0") >= 0 { + if annotations != nil { + annotations[naming.DefaultContainerAnnotation] = naming.PGBackRestRepoContainerName + } else { + annotations = map[string]string{ + naming.DefaultContainerAnnotation: naming.PGBackRestRepoContainerName, + } + } + } + jobSpec := &batchv1.JobSpec{ Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: annotations}, @@ -1348,7 +1357,10 @@ func (r *Reconciler) generateRestoreJobIntent(cluster *v1beta1.PostgresCluster, annotations := naming.Merge( cluster.Spec.Metadata.GetAnnotationsOrNil(), cluster.Spec.Backups.PGBackRest.Metadata.GetAnnotationsOrNil(), - map[string]string{naming.PGBackRestConfigHash: configHash}) + map[string]string{ + naming.PGBackRestConfigHash: configHash, + naming.DefaultContainerAnnotation: naming.PGBackRestRestoreContainerName, + }) labels := naming.Merge( cluster.Spec.Metadata.GetLabelsOrNil(), cluster.Spec.Backups.PGBackRest.Metadata.GetLabelsOrNil(), @@ -1965,7 +1977,7 @@ func (r *Reconciler) copyConfigurationResources(ctx context.Context, cluster, if sourceCluster.Spec.Backups.PGBackRest.Configuration[i].Secret != nil { secretProjection := sourceCluster.Spec.Backups.PGBackRest.Configuration[i].Secret secretCopy := &corev1.Secret{} - secretName := types.NamespacedName{ + secretName := client.ObjectKey{ Name: secretProjection.Name, Namespace: sourceCluster.Namespace, } @@ -2021,7 +2033,7 @@ func (r *Reconciler) copyConfigurationResources(ctx context.Context, cluster, if sourceCluster.Spec.Backups.PGBackRest.Configuration[i].ConfigMap != nil { configMapProjection := sourceCluster.Spec.Backups.PGBackRest.Configuration[i].ConfigMap configMapCopy := &corev1.ConfigMap{} - configMapName := types.NamespacedName{ + configMapName := client.ObjectKey{ Name: configMapProjection.Name, Namespace: sourceCluster.Namespace, } @@ -2084,8 +2096,7 @@ func (r *Reconciler) reconcilePGBackRestConfig(ctx context.Context, backrestConfig := pgbackrest.CreatePGBackRestConfigMapIntent(postgresCluster, repoHostName, configHash, serviceName, serviceNamespace, instanceNames) - if err := controllerutil.SetControllerReference(postgresCluster, backrestConfig, - r.Client.Scheme()); err != nil { + if err := r.setControllerReference(postgresCluster, backrestConfig); err != nil { return err } if err := r.apply(ctx, backrestConfig); err != nil { diff --git a/internal/controller/postgrescluster/pgbackrest_test.go b/internal/controller/postgrescluster/pgbackrest_test.go index 8c5085f087..8d321504eb 100644 --- a/internal/controller/postgrescluster/pgbackrest_test.go +++ b/internal/controller/postgrescluster/pgbackrest_test.go @@ -25,9 +25,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/rand" @@ -38,6 +36,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" + "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/internal/naming" "github.com/percona/percona-postgresql-operator/internal/pgbackrest" @@ -3754,7 +3753,7 @@ func TestSetScheduledJobStatus(t *testing.T) { // create a PostgresCluster to test with postgresCluster := fakePostgresCluster(clusterName, ns.GetName(), clusterUID, true) - testJob := &batchv1.Job{ + uList, err := runtime.ToUnstructuredList(&batchv1.JobList{Items: []batchv1.Job{{ TypeMeta: metav1.TypeMeta{ Kind: "Job", }, @@ -3767,18 +3766,8 @@ func TestSetScheduledJobStatus(t *testing.T) { Succeeded: 2, Failed: 3, }, - } - - // convert the runtime.Object to an unstructured object - unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(testJob) + }}}) assert.NilError(t, err) - unstructuredJob := &unstructured.Unstructured{ - Object: unstructuredObj, - } - - // add it to an unstructured list - uList := &unstructured.UnstructuredList{} - uList.Items = append(uList.Items, *unstructuredJob) // set the status r.setScheduledJobStatus(ctx, postgresCluster, uList.Items) @@ -3793,7 +3782,7 @@ func TestSetScheduledJobStatus(t *testing.T) { // create a PostgresCluster to test with postgresCluster := fakePostgresCluster(clusterName, ns.GetName(), clusterUID, true) - testJob := &batchv1.Job{ + uList, err := runtime.ToUnstructuredList(&batchv1.JobList{Items: []batchv1.Job{{ TypeMeta: metav1.TypeMeta{ Kind: "Job", }, @@ -3805,18 +3794,8 @@ func TestSetScheduledJobStatus(t *testing.T) { Succeeded: 2, Failed: 3, }, - } - - // convert the runtime.Object to an unstructured object - unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(testJob) + }}}) assert.NilError(t, err) - unstructuredJob := &unstructured.Unstructured{ - Object: unstructuredObj, - } - - // add it to an unstructured list - uList := &unstructured.UnstructuredList{} - uList.Items = append(uList.Items, *unstructuredJob) // set the status r.setScheduledJobStatus(ctx, postgresCluster, uList.Items) diff --git a/internal/controller/postgrescluster/pgbouncer.go b/internal/controller/postgrescluster/pgbouncer.go index 2fcd2802ff..3dd963f77a 100644 --- a/internal/controller/postgrescluster/pgbouncer.go +++ b/internal/controller/postgrescluster/pgbouncer.go @@ -385,7 +385,17 @@ func (r *Reconciler) generatePGBouncerDeployment( } deploy.Spec.Template.Annotations = naming.Merge( cluster.Spec.Metadata.GetAnnotationsOrNil(), - cluster.Spec.Proxy.PGBouncer.Metadata.GetAnnotationsOrNil()) + cluster.Spec.Proxy.PGBouncer.Metadata.GetAnnotationsOrNil(), + ) + if cluster.CompareVersion("2.7.0") >= 0 { + deploy.Spec.Template.Annotations = naming.Merge( + cluster.Spec.Metadata.GetAnnotationsOrNil(), + cluster.Spec.Proxy.PGBouncer.Metadata.GetAnnotationsOrNil(), + map[string]string{ + naming.DefaultContainerAnnotation: naming.ContainerPGBouncer, + }, + ) + } deploy.Spec.Template.Labels = naming.Merge( cluster.Spec.Metadata.GetLabelsOrNil(), cluster.Spec.Proxy.PGBouncer.Metadata.GetLabelsOrNil(), diff --git a/internal/controller/postgrescluster/pgbouncer_test.go b/internal/controller/postgrescluster/pgbouncer_test.go index 9f92ee1857..82c152b857 100644 --- a/internal/controller/postgrescluster/pgbouncer_test.go +++ b/internal/controller/postgrescluster/pgbouncer_test.go @@ -6,10 +6,10 @@ package postgrescluster import ( "context" + "errors" "strconv" "testing" - "github.com/pkg/errors" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" @@ -384,7 +384,7 @@ func TestGeneratePGBouncerDeployment(t *testing.T) { cluster.Namespace = "ns3" cluster.Name = "test-cluster" cluster.Labels = map[string]string{ - naming.LabelVersion: "2.3.0", + naming.LabelVersion: "2.7.0", } t.Run("Unspecified", func(t *testing.T) { @@ -456,6 +456,7 @@ namespace: ns3 // Annotations present in the pod template. assert.DeepEqual(t, deploy.Spec.Template.Annotations, map[string]string{ "a": "v1", + "kubectl.kubernetes.io/default-container": "pgbouncer", }) // Labels present in the pod template. diff --git a/internal/controller/postgrescluster/pki_test.go b/internal/controller/postgrescluster/pki_test.go index 3b907f9133..eabdd683ff 100644 --- a/internal/controller/postgrescluster/pki_test.go +++ b/internal/controller/postgrescluster/pki_test.go @@ -12,7 +12,6 @@ import ( "strings" "testing" - "github.com/pkg/errors" "gotest.tools/v3/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -149,8 +148,7 @@ func TestReconcileCerts(t *testing.T) { rootCertMeta := naming.PostgresRootCASecret(cluster1) emptyRootSecret.ObjectMeta = rootCertMeta emptyRootSecret.Data = make(map[string][]byte) - err = errors.WithStack(r.apply(ctx, emptyRootSecret)) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, emptyRootSecret)) // reconcile the root cert secret, creating a new root cert returnedRoot, err := r.reconcileRootCertificate(ctx, cluster1) @@ -208,7 +206,7 @@ func TestReconcileCerts(t *testing.T) { rootCertMeta := naming.PostgresRootCASecret(cluster1) emptyRootSecret.ObjectMeta = rootCertMeta emptyRootSecret.Data = make(map[string][]byte) - err = errors.WithStack(r.apply(ctx, emptyRootSecret)) + assert.NilError(t, r.apply(ctx, emptyRootSecret)) // reconcile the root cert secret newRootCert, err := r.reconcileRootCertificate(ctx, cluster1) @@ -337,8 +335,7 @@ func TestReconcileCerts(t *testing.T) { rootCertMeta := naming.PostgresRootCASecret(cluster1) emptyRootSecret.ObjectMeta = rootCertMeta emptyRootSecret.Data = make(map[string][]byte) - err = errors.WithStack(r.apply(ctx, emptyRootSecret)) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, emptyRootSecret)) // reconcile the root cert secret, creating a new root cert returnedRoot, err := r.reconcileRootCertificate(ctx, cluster1) @@ -398,7 +395,7 @@ func getCertFromSecret( // get the cert from the secret secretCRT, ok := secret.Data[dataKey] if !ok { - return nil, errors.New(fmt.Sprintf("could not retrieve %s", dataKey)) + return nil, fmt.Errorf("could not retrieve %s", dataKey) } // parse the cert from binary encoded data diff --git a/internal/controller/postgrescluster/postgres_test.go b/internal/controller/postgrescluster/postgres_test.go index de39a3c0c0..48fc672a34 100644 --- a/internal/controller/postgrescluster/postgres_test.go +++ b/internal/controller/postgrescluster/postgres_test.go @@ -6,6 +6,7 @@ package postgrescluster import ( "context" + "errors" "fmt" "io" "testing" @@ -13,7 +14,6 @@ import ( "github.com/go-logr/logr/funcr" "github.com/google/go-cmp/cmp/cmpopts" volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" - "github.com/pkg/errors" "gotest.tools/v3/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" diff --git a/internal/controller/postgrescluster/snapshots.go b/internal/controller/postgrescluster/snapshots.go index 6c9ada6518..e3c9be0792 100644 --- a/internal/controller/postgrescluster/snapshots.go +++ b/internal/controller/postgrescluster/snapshots.go @@ -100,7 +100,7 @@ func (r *Reconciler) reconcileVolumeSnapshots(ctx context.Context, r.Recorder.Event(postgrescluster, corev1.EventTypeWarning, "VolumeSnapshotError", *snapshotWithLatestError.Status.Error.Message) for _, snapshot := range snapshots.Items { - if snapshot.Status.Error != nil && + if snapshot.Status != nil && snapshot.Status.Error != nil && snapshot.Status.Error.Time.Before(snapshotWithLatestError.Status.Error.Time) { err = r.deleteControlled(ctx, postgrescluster, &snapshot) if err != nil { @@ -536,7 +536,7 @@ func getSnapshotWithLatestError(snapshots *volumesnapshotv1.VolumeSnapshotList) }, } for _, snapshot := range snapshots.Items { - if snapshot.Status.Error != nil && + if snapshot.Status != nil && snapshot.Status.Error != nil && snapshotWithLatestError.Status.Error.Time.Before(snapshot.Status.Error.Time) { snapshotWithLatestError = snapshot } @@ -576,7 +576,7 @@ func getLatestReadySnapshot(snapshots *volumesnapshotv1.VolumeSnapshotList) *vol }, } for _, snapshot := range snapshots.Items { - if snapshot.Status.ReadyToUse != nil && *snapshot.Status.ReadyToUse && + if snapshot.Status != nil && snapshot.Status.ReadyToUse != nil && *snapshot.Status.ReadyToUse && latestReadySnapshot.Status.CreationTime.Before(snapshot.Status.CreationTime) { latestReadySnapshot = snapshot } diff --git a/internal/controller/postgrescluster/snapshots_test.go b/internal/controller/postgrescluster/snapshots_test.go index 2783a4ecc5..702046e258 100644 --- a/internal/controller/postgrescluster/snapshots_test.go +++ b/internal/controller/postgrescluster/snapshots_test.go @@ -72,34 +72,29 @@ func TestReconcileVolumeSnapshots(t *testing.T) { volumeSnapshotClassName := "my-snapshotclass" snapshot, err := r.generateVolumeSnapshot(cluster, *pvc, volumeSnapshotClassName) assert.NilError(t, err) - err = errors.WithStack(r.apply(ctx, snapshot)) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, snapshot)) // Get all snapshots for this cluster and assert 1 exists selectSnapshots, err := naming.AsSelector(naming.Cluster(cluster.Name)) assert.NilError(t, err) snapshots := &volumesnapshotv1.VolumeSnapshotList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, snapshots, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectSnapshots}, )) - assert.NilError(t, err) assert.Equal(t, len(snapshots.Items), 1) // Reconcile snapshots - err = r.reconcileVolumeSnapshots(ctx, cluster, pvc) - assert.NilError(t, err) + assert.NilError(t, r.reconcileVolumeSnapshots(ctx, cluster, pvc)) // Get all snapshots for this cluster and assert 0 exist - assert.NilError(t, err) snapshots = &volumesnapshotv1.VolumeSnapshotList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, snapshots, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectSnapshots}, )) - assert.NilError(t, err) assert.Equal(t, len(snapshots.Items), 0) }) @@ -131,8 +126,7 @@ func TestReconcileVolumeSnapshots(t *testing.T) { } // Reconcile - err = r.reconcileVolumeSnapshots(ctx, cluster, pvc) - assert.NilError(t, err) + assert.NilError(t, r.reconcileVolumeSnapshots(ctx, cluster, pvc)) // Assert warning event was created and has expected attributes if assert.Check(t, len(recorder.Events) > 0) { @@ -173,19 +167,17 @@ func TestReconcileVolumeSnapshots(t *testing.T) { } // Reconcile - err = r.reconcileVolumeSnapshots(ctx, cluster, pvc) - assert.NilError(t, err) + assert.NilError(t, r.reconcileVolumeSnapshots(ctx, cluster, pvc)) // Assert no snapshots exist selectSnapshots, err := naming.AsSelector(naming.Cluster(cluster.Name)) assert.NilError(t, err) snapshots := &volumesnapshotv1.VolumeSnapshotList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, snapshots, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectSnapshots}, )) - assert.NilError(t, err) assert.Equal(t, len(snapshots.Items), 0) }) @@ -244,18 +236,15 @@ func TestReconcileVolumeSnapshots(t *testing.T) { }, }, } - err := errors.WithStack(r.setControllerReference(cluster, snapshot1)) - assert.NilError(t, err) - err = r.apply(ctx, snapshot1) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(cluster, snapshot1)) + assert.NilError(t, r.apply(ctx, snapshot1)) // Update snapshot status truePtr := initialize.Bool(true) snapshot1.Status = &volumesnapshotv1.VolumeSnapshotStatus{ ReadyToUse: truePtr, } - err = r.Client.Status().Update(ctx, snapshot1) - assert.NilError(t, err) + assert.NilError(t, r.Client.Status().Update(ctx, snapshot1)) // Create second snapshot with different annotation value snapshot2 := &volumesnapshotv1.VolumeSnapshot{ @@ -279,38 +268,32 @@ func TestReconcileVolumeSnapshots(t *testing.T) { }, }, } - err = errors.WithStack(r.setControllerReference(cluster, snapshot2)) - assert.NilError(t, err) - err = r.apply(ctx, snapshot2) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(cluster, snapshot2)) + assert.NilError(t, r.apply(ctx, snapshot2)) // Update second snapshot's status snapshot2.Status = &volumesnapshotv1.VolumeSnapshotStatus{ ReadyToUse: truePtr, } - err = r.Client.Status().Update(ctx, snapshot2) - assert.NilError(t, err) + assert.NilError(t, r.Client.Status().Update(ctx, snapshot2)) // Reconcile - err = r.reconcileVolumeSnapshots(ctx, cluster, pvc) - assert.NilError(t, err) + assert.NilError(t, r.reconcileVolumeSnapshots(ctx, cluster, pvc)) // Assert first snapshot exists and second snapshot was deleted selectSnapshots, err := naming.AsSelector(naming.Cluster(cluster.Name)) assert.NilError(t, err) snapshots := &volumesnapshotv1.VolumeSnapshotList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, snapshots, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectSnapshots}, )) - assert.NilError(t, err) assert.Equal(t, len(snapshots.Items), 1) assert.Equal(t, snapshots.Items[0].Name, "first-snapshot") // Cleanup - err = r.deleteControlled(ctx, cluster, snapshot1) - assert.NilError(t, err) + assert.NilError(t, r.deleteControlled(ctx, cluster, snapshot1)) }) t.Run("SnapshotsEnabledCreateSnapshot", func(t *testing.T) { @@ -347,19 +330,17 @@ func TestReconcileVolumeSnapshots(t *testing.T) { } // Reconcile - err = r.reconcileVolumeSnapshots(ctx, cluster, pvc) - assert.NilError(t, err) + assert.NilError(t, r.reconcileVolumeSnapshots(ctx, cluster, pvc)) // Assert that a snapshot was created selectSnapshots, err := naming.AsSelector(naming.Cluster(cluster.Name)) assert.NilError(t, err) snapshots := &volumesnapshotv1.VolumeSnapshotList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, snapshots, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectSnapshots}, )) - assert.NilError(t, err) assert.Equal(t, len(snapshots.Items), 1) assert.Equal(t, snapshots.Items[0].Annotations[naming.PGBackRestBackupJobCompletion], "another-backup-timestamp") @@ -413,21 +394,18 @@ func TestReconcileDedicatedSnapshotVolume(t *testing.T) { }, Spec: testVolumeClaimSpec(), } - err = errors.WithStack(r.setControllerReference(cluster, pvc)) - assert.NilError(t, err) - err = r.apply(ctx, pvc) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(cluster, pvc)) + assert.NilError(t, r.apply(ctx, pvc)) // Assert that the pvc was created selectPvcs, err := naming.AsSelector(naming.Cluster(cluster.Name)) assert.NilError(t, err) pvcs := &corev1.PersistentVolumeClaimList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, pvcs, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectPvcs}, )) - assert.NilError(t, err) assert.Equal(t, len(pvcs.Items), 1) // Create volumes for reconcile @@ -471,12 +449,11 @@ func TestReconcileDedicatedSnapshotVolume(t *testing.T) { selectPvcs, err := naming.AsSelector(naming.Cluster(cluster.Name)) assert.NilError(t, err) pvcs := &corev1.PersistentVolumeClaimList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, pvcs, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectPvcs}, )) - assert.NilError(t, err) assert.Equal(t, len(pvcs.Items), 1) }) @@ -535,12 +512,11 @@ func TestReconcileDedicatedSnapshotVolume(t *testing.T) { restoreJobs := &batchv1.JobList{} selectJobs, err := naming.AsSelector(naming.ClusterRestoreJobs(cluster.Name)) assert.NilError(t, err) - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, restoreJobs, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectJobs}, )) - assert.NilError(t, err) assert.Equal(t, len(restoreJobs.Items), 1) assert.Assert(t, restoreJobs.Items[0].Annotations[naming.PGBackRestBackupJobCompletion] != "") }) @@ -594,10 +570,8 @@ func TestReconcileDedicatedSnapshotVolume(t *testing.T) { restoreJob.Annotations = map[string]string{ naming.PGBackRestBackupJobCompletion: backupJob.Status.CompletionTime.Format(time.RFC3339), } - err = errors.WithStack(r.setControllerReference(cluster, restoreJob)) - assert.NilError(t, err) - err = r.apply(ctx, restoreJob) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(cluster, restoreJob)) + assert.NilError(t, r.apply(ctx, restoreJob)) restoreJob.Status = batchv1.JobStatus{ Succeeded: 1, @@ -619,8 +593,7 @@ func TestReconcileDedicatedSnapshotVolume(t *testing.T) { }, }, } - err = r.Client.Status().Update(ctx, restoreJob) - assert.NilError(t, err) + assert.NilError(t, r.Client.Status().Update(ctx, restoreJob)) // Create instance set and volumes for reconcile sts := &appsv1.StatefulSet{} @@ -636,12 +609,11 @@ func TestReconcileDedicatedSnapshotVolume(t *testing.T) { restoreJobs := &batchv1.JobList{} selectJobs, err := naming.AsSelector(naming.ClusterRestoreJobs(cluster.Name)) assert.NilError(t, err) - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, restoreJobs, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectJobs}, )) - assert.NilError(t, err) assert.Equal(t, len(restoreJobs.Items), 0) // Assert pvc was annotated @@ -697,10 +669,8 @@ func TestReconcileDedicatedSnapshotVolume(t *testing.T) { restoreJob.Annotations = map[string]string{ naming.PGBackRestBackupJobCompletion: backupJob.Status.CompletionTime.Format(time.RFC3339), } - err = errors.WithStack(r.setControllerReference(cluster, restoreJob)) - assert.NilError(t, err) - err = r.apply(ctx, restoreJob) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(cluster, restoreJob)) + assert.NilError(t, r.apply(ctx, restoreJob)) restoreJob.Status = batchv1.JobStatus{ Succeeded: 0, @@ -799,19 +769,17 @@ func TestDedicatedSnapshotVolumeRestore(t *testing.T) { backupJob := testBackupJob(cluster, "backup-job-dedicated-snapshot-exists-1") backupJob.Status.CompletionTime = ¤tTime - err := r.dedicatedSnapshotVolumeRestore(ctx, cluster, pvc, backupJob) - assert.NilError(t, err) + assert.NilError(t, r.dedicatedSnapshotVolumeRestore(ctx, cluster, pvc, backupJob)) // Assert a restore job was created that has the correct annotation jobs := &batchv1.JobList{} selectJobs, err := naming.AsSelector(naming.ClusterRestoreJobs(cluster.Name)) assert.NilError(t, err) - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, jobs, client.InNamespace(cluster.Namespace), client.MatchingLabelsSelector{Selector: selectJobs}, )) - assert.NilError(t, err) assert.Equal(t, len(jobs.Items), 1) assert.Equal(t, jobs.Items[0].Annotations[naming.PGBackRestBackupJobCompletion], backupJob.Status.CompletionTime.Format(time.RFC3339)) @@ -923,8 +891,7 @@ func TestGetDedicatedSnapshotVolumeRestoreJob(t *testing.T) { job3.Name = "restore-job-3" job3.Namespace = ns.Name - err = r.apply(ctx, job3) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, job3)) dsvRestoreJob, err := r.getDedicatedSnapshotVolumeRestoreJob(ctx, cluster) assert.NilError(t, err) @@ -936,7 +903,6 @@ func TestGetDedicatedSnapshotVolumeRestoreJob(t *testing.T) { func TestGetLatestCompleteBackupJob(t *testing.T) { ctx := context.Background() _, cc := setupKubernetes(t) - // require.ParallelCapacity(t, 1) r := &Reconciler{ Client: cc, @@ -977,12 +943,10 @@ func TestGetLatestCompleteBackupJob(t *testing.T) { job2 := testBackupJob(cluster, "backup-job-one-complete-2") job2.Namespace = ns.Name - err = r.apply(ctx, job2) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, job2)) // Get job1 and update Status. - err = r.Client.Get(ctx, client.ObjectKeyFromObject(job1), job1) - assert.NilError(t, err) + assert.NilError(t, r.Client.Get(ctx, client.ObjectKeyFromObject(job1), job1)) job1.Status = batchv1.JobStatus{ Succeeded: 1, @@ -1004,8 +968,7 @@ func TestGetLatestCompleteBackupJob(t *testing.T) { }, }, } - err = r.Client.Status().Update(ctx, job1) - assert.NilError(t, err) + assert.NilError(t, r.Client.Status().Update(ctx, job1)) latestCompleteBackupJob, err := r.getLatestCompleteBackupJob(ctx, cluster) assert.NilError(t, err) @@ -1026,12 +989,10 @@ func TestGetLatestCompleteBackupJob(t *testing.T) { job2 := testBackupJob(cluster, "backup-job-two-complete-2") job2.Namespace = ns.Name - err = r.apply(ctx, job2) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, job2)) // Get job1 and update Status. - err = r.Client.Get(ctx, client.ObjectKeyFromObject(job1), job1) - assert.NilError(t, err) + assert.NilError(t, r.Client.Get(ctx, client.ObjectKeyFromObject(job1), job1)) job1.Status = batchv1.JobStatus{ Succeeded: 1, @@ -1053,12 +1014,10 @@ func TestGetLatestCompleteBackupJob(t *testing.T) { }, }, } - err = r.Client.Status().Update(ctx, job1) - assert.NilError(t, err) + assert.NilError(t, r.Client.Status().Update(ctx, job1)) // Get job2 and update Status. - err = r.Client.Get(ctx, client.ObjectKeyFromObject(job2), job2) - assert.NilError(t, err) + assert.NilError(t, r.Client.Get(ctx, client.ObjectKeyFromObject(job2), job2)) job2.Status = batchv1.JobStatus{ Succeeded: 1, @@ -1080,8 +1039,7 @@ func TestGetLatestCompleteBackupJob(t *testing.T) { }, }, } - err = r.Client.Status().Update(ctx, job2) - assert.NilError(t, err) + assert.NilError(t, r.Client.Status().Update(ctx, job2)) latestCompleteBackupJob, err := r.getLatestCompleteBackupJob(ctx, cluster) assert.NilError(t, err) @@ -1096,6 +1054,17 @@ func TestGetSnapshotWithLatestError(t *testing.T) { assert.Check(t, snapshotWithLatestError == nil) }) + t.Run("NoSnapshotsWithStatus", func(t *testing.T) { + snapshotList := &volumesnapshotv1.VolumeSnapshotList{ + Items: []volumesnapshotv1.VolumeSnapshot{ + {}, + {}, + }, + } + snapshotWithLatestError := getSnapshotWithLatestError(snapshotList) + assert.Check(t, snapshotWithLatestError == nil) + }) + t.Run("NoSnapshotsWithErrors", func(t *testing.T) { snapshotList := &volumesnapshotv1.VolumeSnapshotList{ Items: []volumesnapshotv1.VolumeSnapshot{ @@ -1220,8 +1189,7 @@ func TestGetSnapshotsForCluster(t *testing.T) { } snapshot.Spec.Source.PersistentVolumeClaimName = initialize.String("some-pvc-name") snapshot.Spec.VolumeSnapshotClassName = initialize.String("some-class-name") - err := r.apply(ctx, snapshot) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, snapshot)) snapshots, err := r.getSnapshotsForCluster(ctx, cluster) assert.NilError(t, err) @@ -1262,8 +1230,7 @@ func TestGetSnapshotsForCluster(t *testing.T) { } snapshot2.Spec.Source.PersistentVolumeClaimName = initialize.String("another-pvc-name") snapshot2.Spec.VolumeSnapshotClassName = initialize.String("another-class-name") - err = r.apply(ctx, snapshot2) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, snapshot2)) snapshots, err := r.getSnapshotsForCluster(ctx, cluster) assert.NilError(t, err) @@ -1305,8 +1272,7 @@ func TestGetSnapshotsForCluster(t *testing.T) { } snapshot2.Spec.Source.PersistentVolumeClaimName = initialize.String("another-pvc-name") snapshot2.Spec.VolumeSnapshotClassName = initialize.String("another-class-name") - err = r.apply(ctx, snapshot2) - assert.NilError(t, err) + assert.NilError(t, r.apply(ctx, snapshot2)) snapshots, err := r.getSnapshotsForCluster(ctx, cluster) assert.NilError(t, err) @@ -1321,6 +1287,17 @@ func TestGetLatestReadySnapshot(t *testing.T) { assert.Assert(t, latestReadySnapshot == nil) }) + t.Run("NoSnapshotsWithStatus", func(t *testing.T) { + snapshotList := &volumesnapshotv1.VolumeSnapshotList{ + Items: []volumesnapshotv1.VolumeSnapshot{ + {}, + {}, + }, + } + latestReadySnapshot := getLatestReadySnapshot(snapshotList) + assert.Assert(t, latestReadySnapshot == nil) + }) + t.Run("NoReadySnapshots", func(t *testing.T) { snapshotList := &volumesnapshotv1.VolumeSnapshotList{ Items: []volumesnapshotv1.VolumeSnapshot{ @@ -1455,24 +1432,20 @@ func TestDeleteSnapshots(t *testing.T) { }, }, } - err := errors.WithStack(r.setControllerReference(rhinoCluster, snapshot1)) - assert.NilError(t, err) - err = r.apply(ctx, snapshot1) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(rhinoCluster, snapshot1)) + assert.NilError(t, r.apply(ctx, snapshot1)) snapshotList := &volumesnapshotv1.VolumeSnapshotList{ Items: []volumesnapshotv1.VolumeSnapshot{ *snapshot1, }, } - err = r.deleteSnapshots(ctx, cluster, snapshotList) - assert.NilError(t, err) + assert.NilError(t, r.deleteSnapshots(ctx, cluster, snapshotList)) existingSnapshots := &volumesnapshotv1.VolumeSnapshotList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, existingSnapshots, client.InNamespace(ns.Namespace), )) - assert.NilError(t, err) assert.Equal(t, len(existingSnapshots.Items), 1) }) @@ -1493,10 +1466,8 @@ func TestDeleteSnapshots(t *testing.T) { }, }, } - err := errors.WithStack(r.setControllerReference(rhinoCluster, snapshot1)) - assert.NilError(t, err) - err = r.apply(ctx, snapshot1) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(rhinoCluster, snapshot1)) + assert.NilError(t, r.apply(ctx, snapshot1)) snapshot2 := &volumesnapshotv1.VolumeSnapshot{ TypeMeta: metav1.TypeMeta{ @@ -1513,24 +1484,20 @@ func TestDeleteSnapshots(t *testing.T) { }, }, } - err = errors.WithStack(r.setControllerReference(cluster, snapshot2)) - assert.NilError(t, err) - err = r.apply(ctx, snapshot2) - assert.NilError(t, err) + assert.NilError(t, r.setControllerReference(cluster, snapshot2)) + assert.NilError(t, r.apply(ctx, snapshot2)) snapshotList := &volumesnapshotv1.VolumeSnapshotList{ Items: []volumesnapshotv1.VolumeSnapshot{ *snapshot1, *snapshot2, }, } - err = r.deleteSnapshots(ctx, cluster, snapshotList) - assert.NilError(t, err) + assert.NilError(t, r.deleteSnapshots(ctx, cluster, snapshotList)) existingSnapshots := &volumesnapshotv1.VolumeSnapshotList{} - err = errors.WithStack( + assert.NilError(t, r.Client.List(ctx, existingSnapshots, client.InNamespace(ns.Namespace), )) - assert.NilError(t, err) assert.Equal(t, len(existingSnapshots.Items), 1) assert.Equal(t, existingSnapshots.Items[0].Name, "first-snapshot") }) diff --git a/internal/controller/postgrescluster/suite_test.go b/internal/controller/postgrescluster/suite_test.go index 1dbd36bd1e..99f779a345 100644 --- a/internal/controller/postgrescluster/suite_test.go +++ b/internal/controller/postgrescluster/suite_test.go @@ -7,7 +7,6 @@ package postgrescluster import ( "context" "os" - "path/filepath" "strings" "testing" @@ -20,19 +19,17 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/logging" + "github.com/percona/percona-postgresql-operator/internal/testing/require" ) var suite struct { Client client.Client Config *rest.Config - Environment *envtest.Environment ServerVersion *version.Version Manager manager.Manager @@ -53,21 +50,7 @@ var _ = BeforeSuite(func() { log.SetLogger(logging.FromContext(context.Background())) By("bootstrapping test environment") - suite.Environment = &envtest.Environment{ - CRDDirectoryPaths: []string{ - filepath.Join("..", "..", "..", "config", "crd", "bases"), - filepath.Join("..", "..", "..", "hack", "tools", "external-snapshotter", "client", "config", "crd"), - }, - } - - _, err := suite.Environment.Start() - Expect(err).ToNot(HaveOccurred()) - - DeferCleanup(suite.Environment.Stop) - - suite.Config = suite.Environment.Config - suite.Client, err = client.New(suite.Config, client.Options{Scheme: runtime.Scheme}) - Expect(err).ToNot(HaveOccurred()) + suite.Config, suite.Client = require.Kubernetes2(GinkgoT()) dc, err := discovery.NewDiscoveryClientForConfig(suite.Config) Expect(err).ToNot(HaveOccurred()) diff --git a/internal/controller/postgrescluster/volumes.go b/internal/controller/postgrescluster/volumes.go index ae7ac39dd9..16d975c096 100644 --- a/internal/controller/postgrescluster/volumes.go +++ b/internal/controller/postgrescluster/volumes.go @@ -476,7 +476,9 @@ func (r *Reconciler) reconcileMovePGDataDir(ctx context.Context, jobSpec := &batchv1.JobSpec{ Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{Labels: labels}, + ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: map[string]string{ + naming.DefaultContainerAnnotation: naming.ContainerJobMovePGDataDir, + }}, Spec: corev1.PodSpec{ Tolerations: cluster.Spec.DataSource.Volumes.PGDataVolume.Tolerations, // K8SPG-479 // Set the image pull secrets, if any exist. @@ -594,7 +596,9 @@ func (r *Reconciler) reconcileMoveWALDir(ctx context.Context, jobSpec := &batchv1.JobSpec{ Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{Labels: labels}, + ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: map[string]string{ + naming.DefaultContainerAnnotation: naming.ContainerJobMovePGWALDir, + }}, Spec: corev1.PodSpec{ Tolerations: cluster.Spec.DataSource.Volumes.PGWALVolume.Tolerations, // K8SPG-479 // Set the image pull secrets, if any exist. @@ -717,7 +721,9 @@ func (r *Reconciler) reconcileMoveRepoDir(ctx context.Context, jobSpec := &batchv1.JobSpec{ Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{Labels: labels}, + ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: map[string]string{ + naming.DefaultContainerAnnotation: naming.ContainerJobMovePGBackRestRepoDir, + }}, Spec: corev1.PodSpec{ Tolerations: cluster.Spec.DataSource.Volumes.PGBackRestVolume.Tolerations, // K8SPG-479 // Set the image pull secrets, if any exist. diff --git a/internal/controller/runtime/conversion.go b/internal/controller/runtime/conversion.go new file mode 100644 index 0000000000..aa8e272c14 --- /dev/null +++ b/internal/controller/runtime/conversion.go @@ -0,0 +1,73 @@ +// Copyright 2021 - 2024 Crunchy Data Solutions, Inc. +// +// SPDX-License-Identifier: Apache-2.0 + +package runtime + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type ( + GR = schema.GroupResource + GV = schema.GroupVersion + GVK = schema.GroupVersionKind + GVR = schema.GroupVersionResource +) + +// These functions call the [runtime.DefaultUnstructuredConverter] with some additional type safety. +// An [unstructured.Unstructured] should always be paired with a [client.Object], and +// an [unstructured.UnstructuredList] should always be paired with a [client.ObjectList]. + +// FromUnstructuredList returns a copy of list by marshaling through JSON. +func FromUnstructuredList[ + // *T implements [client.ObjectList] + T any, PT interface { + client.ObjectList + *T + }, +](list *unstructured.UnstructuredList) (*T, error) { + result := new(T) + return result, runtime. + DefaultUnstructuredConverter. + FromUnstructured(list.UnstructuredContent(), result) +} + +// FromUnstructuredObject returns a copy of object by marshaling through JSON. +func FromUnstructuredObject[ + // *T implements [client.Object] + T any, PT interface { + client.Object + *T + }, +](object *unstructured.Unstructured) (*T, error) { + result := new(T) + return result, runtime. + DefaultUnstructuredConverter. + FromUnstructured(object.UnstructuredContent(), result) +} + +// ToUnstructuredList returns a copy of list by marshaling through JSON. +func ToUnstructuredList(list client.ObjectList) (*unstructured.UnstructuredList, error) { + content, err := runtime. + DefaultUnstructuredConverter. + ToUnstructured(list) + + result := new(unstructured.UnstructuredList) + result.SetUnstructuredContent(content) + return result, err +} + +// ToUnstructuredObject returns a copy of object by marshaling through JSON. +func ToUnstructuredObject(object client.Object) (*unstructured.Unstructured, error) { + content, err := runtime. + DefaultUnstructuredConverter. + ToUnstructured(object) + + result := new(unstructured.Unstructured) + result.SetUnstructuredContent(content) + return result, err +} diff --git a/internal/controller/runtime/conversion_test.go b/internal/controller/runtime/conversion_test.go new file mode 100644 index 0000000000..f43a34d989 --- /dev/null +++ b/internal/controller/runtime/conversion_test.go @@ -0,0 +1,46 @@ +// Copyright 2021 - 2024 Crunchy Data Solutions, Inc. +// +// SPDX-License-Identifier: Apache-2.0 + +package runtime_test + +import ( + "testing" + + "gotest.tools/v3/assert" + corev1 "k8s.io/api/core/v1" + + "github.com/percona/percona-postgresql-operator/internal/controller/runtime" +) + +func TestConvertUnstructured(t *testing.T) { + var cm corev1.ConfigMap + cm.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("ConfigMap")) + cm.Namespace = "one" + cm.Name = "two" + cm.Data = map[string]string{"w": "x", "y": "z"} + + t.Run("List", func(t *testing.T) { + original := new(corev1.ConfigMapList) + original.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("ConfigMapList")) + original.Items = []corev1.ConfigMap{*cm.DeepCopy()} + + list, err := runtime.ToUnstructuredList(original) + assert.NilError(t, err) + + converted, err := runtime.FromUnstructuredList[corev1.ConfigMapList](list) + assert.NilError(t, err) + assert.DeepEqual(t, original, converted) + }) + + t.Run("Object", func(t *testing.T) { + original := cm.DeepCopy() + + object, err := runtime.ToUnstructuredObject(original) + assert.NilError(t, err) + + converted, err := runtime.FromUnstructuredObject[corev1.ConfigMap](object) + assert.NilError(t, err) + assert.DeepEqual(t, original, converted) + }) +} diff --git a/internal/controller/standalone_pgadmin/statefulset.go b/internal/controller/standalone_pgadmin/statefulset.go index b10818ee51..917d615a4a 100644 --- a/internal/controller/standalone_pgadmin/statefulset.go +++ b/internal/controller/standalone_pgadmin/statefulset.go @@ -74,7 +74,12 @@ func statefulset( sts.Spec.Selector = &metav1.LabelSelector{ MatchLabels: naming.StandalonePGAdminLabels(pgadmin.Name), } - sts.Spec.Template.Annotations = pgadmin.Spec.Metadata.GetAnnotationsOrNil() + sts.Spec.Template.Annotations = naming.Merge( + pgadmin.Spec.Metadata.GetAnnotationsOrNil(), + map[string]string{ + naming.DefaultContainerAnnotation: naming.ContainerPGAdmin, + }, + ) sts.Spec.Template.Labels = naming.Merge( pgadmin.Spec.Metadata.GetLabelsOrNil(), naming.StandalonePGAdminDataLabels(pgadmin.Name), diff --git a/internal/controller/standalone_pgadmin/statefulset_test.go b/internal/controller/standalone_pgadmin/statefulset_test.go index da7ac2c8e7..1ddd967ede 100644 --- a/internal/controller/standalone_pgadmin/statefulset_test.go +++ b/internal/controller/standalone_pgadmin/statefulset_test.go @@ -73,6 +73,8 @@ func TestReconcilePGAdminStatefulSet(t *testing.T) { template.Spec.Volumes = nil assert.Assert(t, cmp.MarshalMatches(template.ObjectMeta, ` +annotations: + kubectl.kubernetes.io/default-container: pgadmin creationTimestamp: null labels: postgres-operator.crunchydata.com/data: pgadmin @@ -170,6 +172,7 @@ terminationGracePeriodSeconds: 30 assert.Assert(t, cmp.MarshalMatches(template.ObjectMeta, ` annotations: annotation1: annotationvalue + kubectl.kubernetes.io/default-container: pgadmin creationTimestamp: null labels: label1: labelvalue diff --git a/internal/controller/standalone_pgadmin/users.go b/internal/controller/standalone_pgadmin/users.go index dd24bbd9ae..0ab1093f8d 100644 --- a/internal/controller/standalone_pgadmin/users.go +++ b/internal/controller/standalone_pgadmin/users.go @@ -293,11 +293,7 @@ cd $PGADMIN_DIR // to add a user, that user will not be in intentUsers. If errors occurred when attempting to // update a user, the user will be in intentUsers as it existed before. We now want to marshal the // intentUsers to json and write the users.json file to the secret. - usersJSON, err := json.Marshal(intentUsers) - if err != nil { - return err - } - intentUserSecret.Data["users.json"] = usersJSON + intentUserSecret.Data["users.json"], _ = json.Marshal(intentUsers) err = errors.WithStack(r.setControllerReference(pgadmin, intentUserSecret)) if err == nil { diff --git a/internal/controller/standalone_pgadmin/users_test.go b/internal/controller/standalone_pgadmin/users_test.go index 0f75923e12..ce18ddd426 100644 --- a/internal/controller/standalone_pgadmin/users_test.go +++ b/internal/controller/standalone_pgadmin/users_test.go @@ -7,12 +7,12 @@ package standalone_pgadmin import ( "context" "encoding/json" + "errors" "fmt" "io" "strings" "testing" - "github.com/pkg/errors" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -112,7 +112,7 @@ func TestReconcilePGAdminUsers(t *testing.T) { // Simulate a v7 version of pgAdmin by setting stdout to "7" for // podexec call in reconcilePGAdminMajorVersion - stdout.Write([]byte("7")) + _, _ = stdout.Write([]byte("7")) return nil } @@ -147,7 +147,7 @@ func TestReconcilePGAdminUsers(t *testing.T) { // Simulate a v7 version of pgAdmin by setting stdout to "7" for // podexec call in reconcilePGAdminMajorVersion - stdout.Write([]byte("7")) + _, _ = stdout.Write([]byte("7")) return nil } @@ -182,7 +182,7 @@ func TestReconcilePGAdminMajorVersion(t *testing.T) { // Simulate a v7 version of pgAdmin by setting stdout to "7" for // podexec call in reconcilePGAdminMajorVersion - stdout.Write([]byte("7")) + _, _ = stdout.Write([]byte("7")) return nil } @@ -197,7 +197,7 @@ func TestReconcilePGAdminMajorVersion(t *testing.T) { stdin io.Reader, stdout, stderr io.Writer, command ...string, ) error { // Simulate the python call giving bad data (not a version int) - stdout.Write([]byte("asdfjkl;")) + _, _ = stdout.Write([]byte("asdfjkl;")) return nil } @@ -310,8 +310,8 @@ func TestWritePGAdminUsers(t *testing.T) { assert.Equal(t, calls, 1, "PodExec should be called once") secret := &corev1.Secret{ObjectMeta: naming.StandalonePGAdmin(pgadmin)} - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -370,8 +370,8 @@ func TestWritePGAdminUsers(t *testing.T) { assert.Equal(t, updateUserCalls, 1, "The update-user command should be executed once") secret := &corev1.Secret{ObjectMeta: naming.StandalonePGAdmin(pgadmin)} - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -442,8 +442,8 @@ func TestWritePGAdminUsers(t *testing.T) { assert.Equal(t, updateUserCalls, 1, "The update-user command should be executed once") secret := &corev1.Secret{ObjectMeta: naming.StandalonePGAdmin(pgadmin)} - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -487,8 +487,8 @@ func TestWritePGAdminUsers(t *testing.T) { assert.Equal(t, calls, 0, "PodExec should be called zero times") secret := &corev1.Secret{ObjectMeta: naming.StandalonePGAdmin(pgadmin)} - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -529,8 +529,8 @@ func TestWritePGAdminUsers(t *testing.T) { // User in users.json should be unchanged secret := &corev1.Secret{ObjectMeta: naming.StandalonePGAdmin(pgadmin)} - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -547,7 +547,7 @@ func TestWritePGAdminUsers(t *testing.T) { ) error { calls++ - stderr.Write([]byte("issue running setup.py update-user command")) + _, _ = stderr.Write([]byte("issue running setup.py update-user command")) return nil } @@ -556,8 +556,8 @@ func TestWritePGAdminUsers(t *testing.T) { assert.Equal(t, calls, 2, "PodExec should be called once more") // User in users.json should be unchanged - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -609,8 +609,8 @@ func TestWritePGAdminUsers(t *testing.T) { // User in users.json should be unchanged and attempt to add user should not // have succeeded secret := &corev1.Secret{ObjectMeta: naming.StandalonePGAdmin(pgadmin)} - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -627,7 +627,7 @@ func TestWritePGAdminUsers(t *testing.T) { ) error { calls++ - stderr.Write([]byte("issue running setup.py add-user command")) + _, _ = stderr.Write([]byte("issue running setup.py add-user command")) return nil } @@ -637,8 +637,8 @@ func TestWritePGAdminUsers(t *testing.T) { // User in users.json should be unchanged and attempt to add user should not // have succeeded - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -655,7 +655,7 @@ func TestWritePGAdminUsers(t *testing.T) { ) error { calls++ - stdout.Write([]byte("Invalid email address")) + _, _ = stdout.Write([]byte("Invalid email address")) return nil } @@ -665,8 +665,8 @@ func TestWritePGAdminUsers(t *testing.T) { // User in users.json should be unchanged and attempt to add user should not // have succeeded - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) @@ -684,7 +684,7 @@ func TestWritePGAdminUsers(t *testing.T) { ) error { calls++ - stdout.Write([]byte("Password must be at least 6 characters long")) + _, _ = stdout.Write([]byte("Password must be at least 6 characters long")) return nil } @@ -694,8 +694,8 @@ func TestWritePGAdminUsers(t *testing.T) { // User in users.json should be unchanged and attempt to add user should not // have succeeded - assert.NilError(t, errors.WithStack( - reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret))) + assert.NilError(t, + reconciler.Client.Get(ctx, client.ObjectKeyFromObject(secret), secret)) if assert.Check(t, secret.Data["users.json"] != nil) { var usersArr []pgAdminUserForJson assert.NilError(t, json.Unmarshal(secret.Data["users.json"], &usersArr)) diff --git a/internal/controller/standalone_pgadmin/volume_test.go b/internal/controller/standalone_pgadmin/volume_test.go index 2c61e4f3ba..8103943dd8 100644 --- a/internal/controller/standalone_pgadmin/volume_test.go +++ b/internal/controller/standalone_pgadmin/volume_test.go @@ -6,9 +6,9 @@ package standalone_pgadmin import ( "context" + "errors" "testing" - "github.com/pkg/errors" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" diff --git a/internal/feature/features.go b/internal/feature/features.go index db424ead42..ae0d4ac15b 100644 --- a/internal/feature/features.go +++ b/internal/feature/features.go @@ -42,6 +42,9 @@ package feature import ( "context" + "fmt" + "slices" + "strings" "k8s.io/component-base/featuregate" ) @@ -51,7 +54,6 @@ type Feature = featuregate.Feature // Gate indicates what features exist and which are enabled. type Gate interface { Enabled(Feature) bool - String() string } // MutableGate contains features that can be enabled or disabled. @@ -81,6 +83,9 @@ const ( // Support custom sidecars for pgBouncer Pods PGBouncerSidecars = "PGBouncerSidecars" + // Adjust PGUpgrade parallelism according to CPU resources + PGUpgradeCPUConcurrency = "PGUpgradeCPUConcurrency" + // Support tablespace volumes TablespaceVolumes = "TablespaceVolumes" @@ -93,14 +98,15 @@ func NewGate() MutableGate { gate := featuregate.NewFeatureGate() if err := gate.Add(map[Feature]featuregate.FeatureSpec{ - AppendCustomQueries: {Default: false, PreRelease: featuregate.Alpha}, - AutoCreateUserSchema: {Default: true, PreRelease: featuregate.Beta}, - AutoGrowVolumes: {Default: false, PreRelease: featuregate.Alpha}, - BridgeIdentifiers: {Default: false, PreRelease: featuregate.Alpha}, - InstanceSidecars: {Default: false, PreRelease: featuregate.Alpha}, - PGBouncerSidecars: {Default: false, PreRelease: featuregate.Alpha}, - TablespaceVolumes: {Default: false, PreRelease: featuregate.Alpha}, - VolumeSnapshots: {Default: false, PreRelease: featuregate.Alpha}, + AppendCustomQueries: {Default: false, PreRelease: featuregate.Alpha}, + AutoCreateUserSchema: {Default: true, PreRelease: featuregate.Beta}, + AutoGrowVolumes: {Default: false, PreRelease: featuregate.Alpha}, + BridgeIdentifiers: {Default: false, PreRelease: featuregate.Alpha}, + InstanceSidecars: {Default: false, PreRelease: featuregate.Alpha}, + PGBouncerSidecars: {Default: false, PreRelease: featuregate.Alpha}, + PGUpgradeCPUConcurrency: {Default: false, PreRelease: featuregate.Alpha}, + TablespaceVolumes: {Default: false, PreRelease: featuregate.Alpha}, + VolumeSnapshots: {Default: false, PreRelease: featuregate.Alpha}, }); err != nil { panic(err) } @@ -122,11 +128,36 @@ func NewContext(ctx context.Context, gate Gate) context.Context { return context.WithValue(ctx, contextKey{}, gate) } -func ShowGates(ctx context.Context) string { - featuresEnabled := "" - gate, ok := ctx.Value(contextKey{}).(Gate) - if ok { - featuresEnabled = gate.String() +// ShowEnabled returns all the features enabled in the Gate contained in ctx. +func ShowEnabled(ctx context.Context) string { + featuresEnabled := []string{} + if gate, ok := ctx.Value(contextKey{}).(interface { + Gate + GetAll() map[Feature]featuregate.FeatureSpec + }); ok { + specs := gate.GetAll() + for feature := range specs { + // `gate.Enabled` first checks if the feature is enabled; + // then (if not explicitly set by the user), + // it checks if the feature is on/true by default + if gate.Enabled(feature) { + featuresEnabled = append(featuresEnabled, fmt.Sprintf("%s=true", feature)) + } + } + } + slices.Sort(featuresEnabled) + return strings.Join(featuresEnabled, ",") +} + +// ShowAssigned returns the features enabled or disabled by Set and SetFromMap +// in the Gate contained in ctx. +func ShowAssigned(ctx context.Context) string { + featuresAssigned := "" + if gate, ok := ctx.Value(contextKey{}).(interface { + Gate + String() string + }); ok { + featuresAssigned = gate.String() } - return featuresEnabled + return featuresAssigned } diff --git a/internal/feature/features_test.go b/internal/feature/features_test.go index f76dd216e6..b05052a345 100644 --- a/internal/feature/features_test.go +++ b/internal/feature/features_test.go @@ -6,6 +6,7 @@ package feature import ( "context" + "strings" "testing" "gotest.tools/v3/assert" @@ -21,10 +22,9 @@ func TestDefaults(t *testing.T) { assert.Assert(t, false == gate.Enabled(BridgeIdentifiers)) assert.Assert(t, false == gate.Enabled(InstanceSidecars)) assert.Assert(t, false == gate.Enabled(PGBouncerSidecars)) + assert.Assert(t, false == gate.Enabled(PGUpgradeCPUConcurrency)) assert.Assert(t, false == gate.Enabled(TablespaceVolumes)) assert.Assert(t, false == gate.Enabled(VolumeSnapshots)) - - assert.Equal(t, gate.String(), "") } func TestStringFormat(t *testing.T) { @@ -33,7 +33,6 @@ func TestStringFormat(t *testing.T) { assert.NilError(t, gate.Set("")) assert.NilError(t, gate.Set("TablespaceVolumes=true")) - assert.Equal(t, gate.String(), "TablespaceVolumes=true") assert.Assert(t, true == gate.Enabled(TablespaceVolumes)) err := gate.Set("NotAGate=true") @@ -53,13 +52,21 @@ func TestContext(t *testing.T) { t.Parallel() gate := NewGate() ctx := NewContext(context.Background(), gate) - assert.Equal(t, ShowGates(ctx), "") + + assert.Equal(t, ShowAssigned(ctx), "") + assert.Assert(t, ShowEnabled(ctx) != "") // This assumes some feature is enabled by default. assert.NilError(t, gate.Set("TablespaceVolumes=true")) - assert.Assert(t, true == Enabled(ctx, TablespaceVolumes)) - assert.Equal(t, ShowGates(ctx), "TablespaceVolumes=true") + assert.Assert(t, Enabled(ctx, TablespaceVolumes)) + assert.Equal(t, ShowAssigned(ctx), "TablespaceVolumes=true") + assert.Assert(t, + strings.Contains(ShowEnabled(ctx), "TablespaceVolumes=true"), + "got: %v", ShowEnabled(ctx)) assert.NilError(t, gate.SetFromMap(map[string]bool{TablespaceVolumes: false})) - assert.Assert(t, false == Enabled(ctx, TablespaceVolumes)) - assert.Equal(t, ShowGates(ctx), "TablespaceVolumes=false") + assert.Assert(t, !Enabled(ctx, TablespaceVolumes)) + assert.Equal(t, ShowAssigned(ctx), "TablespaceVolumes=false") + assert.Assert(t, + !strings.Contains(ShowEnabled(ctx), "TablespaceVolumes"), + "got: %v", ShowEnabled(ctx)) } diff --git a/internal/kubeapi/patch.go b/internal/kubeapi/patch.go index 973852c17a..fa1bb64d51 100644 --- a/internal/kubeapi/patch.go +++ b/internal/kubeapi/patch.go @@ -18,12 +18,10 @@ var escapeJSONPointer = strings.NewReplacer( "/", "~1", ).Replace -// JSON6902 represents a JSON Patch according to RFC 6902; the same as -// k8s.io/apimachinery/pkg/types.JSONPatchType. -type JSON6902 []interface{} +// JSON6902 represents a JSON Patch according to RFC 6902; the same as [types.JSONPatchType]. +type JSON6902 []any -// NewJSONPatch creates a new JSON Patch according to RFC 6902; the same as -// k8s.io/apimachinery/pkg/types.JSONPatchType. +// NewJSONPatch creates a new JSON Patch according to RFC 6902; the same as [types.JSONPatchType]. func NewJSONPatch() *JSON6902 { return &JSON6902{} } func (*JSON6902) pointer(tokens ...string) string { @@ -50,10 +48,10 @@ func (*JSON6902) pointer(tokens ...string) string { // > // > o If the target location specifies an object member that does exist, // > that member's value is replaced. -func (patch *JSON6902) Add(path ...string) func(value interface{}) *JSON6902 { +func (patch *JSON6902) Add(path ...string) func(value any) *JSON6902 { i := len(*patch) - f := func(value interface{}) *JSON6902 { - (*patch)[i] = map[string]interface{}{ + f := func(value any) *JSON6902 { + (*patch)[i] = map[string]any{ "op": "add", "path": patch.pointer(path...), "value": value, @@ -72,7 +70,7 @@ func (patch *JSON6902) Add(path ...string) func(value interface{}) *JSON6902 { // > // > The target location MUST exist for the operation to be successful. func (patch *JSON6902) Remove(path ...string) *JSON6902 { - *patch = append(*patch, map[string]interface{}{ + *patch = append(*patch, map[string]any{ "op": "remove", "path": patch.pointer(path...), }) @@ -86,10 +84,10 @@ func (patch *JSON6902) Remove(path ...string) *JSON6902 { // > with a new value. // > // > The target location MUST exist for the operation to be successful. -func (patch *JSON6902) Replace(path ...string) func(value interface{}) *JSON6902 { +func (patch *JSON6902) Replace(path ...string) func(value any) *JSON6902 { i := len(*patch) - f := func(value interface{}) *JSON6902 { - (*patch)[i] = map[string]interface{}{ + f := func(value any) *JSON6902 { + (*patch)[i] = map[string]any{ "op": "replace", "path": patch.pointer(path...), "value": value, @@ -103,23 +101,21 @@ func (patch *JSON6902) Replace(path ...string) func(value interface{}) *JSON6902 } // Bytes returns the JSON representation of patch. -func (patch JSON6902) Bytes() ([]byte, error) { return patch.Data(nil) } +func (patch *JSON6902) Bytes() ([]byte, error) { return patch.Data(nil) } // Data returns the JSON representation of patch. -func (patch JSON6902) Data(client.Object) ([]byte, error) { return json.Marshal(patch) } +func (patch *JSON6902) Data(client.Object) ([]byte, error) { return json.Marshal(*patch) } // IsEmpty returns true when patch has no operations. -func (patch JSON6902) IsEmpty() bool { return len(patch) == 0 } +func (patch *JSON6902) IsEmpty() bool { return len(*patch) == 0 } -// Type returns k8s.io/apimachinery/pkg/types.JSONPatchType. -func (patch JSON6902) Type() types.PatchType { return types.JSONPatchType } +// Type returns [types.JSONPatchType]. +func (patch *JSON6902) Type() types.PatchType { return types.JSONPatchType } -// Merge7386 represents a JSON Merge Patch according to RFC 7386; the same as -// k8s.io/apimachinery/pkg/types.MergePatchType. -type Merge7386 map[string]interface{} +// Merge7386 represents a JSON Merge Patch according to RFC 7386; the same as [types.MergePatchType]. +type Merge7386 map[string]any -// NewMergePatch creates a new JSON Merge Patch according to RFC 7386; the same -// as k8s.io/apimachinery/pkg/types.MergePatchType. +// NewMergePatch creates a new JSON Merge Patch according to RFC 7386; the same as [types.MergePatchType]. func NewMergePatch() *Merge7386 { return &Merge7386{} } // Add modifies patch to indicate that the member at path should be added or @@ -130,7 +126,7 @@ func NewMergePatch() *Merge7386 { return &Merge7386{} } // > contain the member, the value is replaced. Null values in the merge // > patch are given special meaning to indicate the removal of existing // > values in the target. -func (patch *Merge7386) Add(path ...string) func(value interface{}) *Merge7386 { +func (patch *Merge7386) Add(path ...string) func(value any) *Merge7386 { position := *patch for len(path) > 1 { @@ -145,10 +141,10 @@ func (patch *Merge7386) Add(path ...string) func(value interface{}) *Merge7386 { } if len(path) < 1 { - return func(interface{}) *Merge7386 { return patch } + return func(any) *Merge7386 { return patch } } - f := func(value interface{}) *Merge7386 { + f := func(value any) *Merge7386 { position[path[0]] = value return patch } @@ -165,13 +161,13 @@ func (patch *Merge7386) Remove(path ...string) *Merge7386 { } // Bytes returns the JSON representation of patch. -func (patch Merge7386) Bytes() ([]byte, error) { return patch.Data(nil) } +func (patch *Merge7386) Bytes() ([]byte, error) { return patch.Data(nil) } // Data returns the JSON representation of patch. -func (patch Merge7386) Data(client.Object) ([]byte, error) { return json.Marshal(patch) } +func (patch *Merge7386) Data(client.Object) ([]byte, error) { return json.Marshal(*patch) } // IsEmpty returns true when patch has no modifications. -func (patch Merge7386) IsEmpty() bool { return len(patch) == 0 } +func (patch *Merge7386) IsEmpty() bool { return len(*patch) == 0 } -// Type returns k8s.io/apimachinery/pkg/types.MergePatchType. -func (patch Merge7386) Type() types.PatchType { return types.MergePatchType } +// Type returns [types.MergePatchType]. +func (patch *Merge7386) Type() types.PatchType { return types.MergePatchType } diff --git a/internal/logging/logr.go b/internal/logging/logr.go index c907997d40..7d6f208744 100644 --- a/internal/logging/logr.go +++ b/internal/logging/logr.go @@ -51,12 +51,12 @@ type sink struct { depth int verbosity int names []string - values []interface{} + values []any // TODO(cbandy): add names or frame to the functions below. - fnError func(error, string, ...interface{}) - fnInfo func(int, string, ...interface{}) + fnError func(error, string, ...any) + fnInfo func(int, string, ...any) } var _ logr.LogSink = (*sink)(nil) @@ -64,7 +64,7 @@ var _ logr.LogSink = (*sink)(nil) func (s *sink) Enabled(level int) bool { return level <= s.verbosity } func (s *sink) Init(info logr.RuntimeInfo) { s.depth = info.CallDepth } -func (s sink) combineValues(kv ...interface{}) []interface{} { +func (s *sink) combineValues(kv ...any) []any { if len(kv) == 0 { return s.values } @@ -74,11 +74,11 @@ func (s sink) combineValues(kv ...interface{}) []interface{} { return kv } -func (s *sink) Error(err error, msg string, kv ...interface{}) { +func (s *sink) Error(err error, msg string, kv ...any) { s.fnError(err, msg, s.combineValues(kv...)...) } -func (s *sink) Info(level int, msg string, kv ...interface{}) { +func (s *sink) Info(level int, msg string, kv ...any) { s.fnInfo(level, msg, s.combineValues(kv...)...) } @@ -89,7 +89,7 @@ func (s *sink) WithName(name string) logr.LogSink { return &out } -func (s *sink) WithValues(kv ...interface{}) logr.LogSink { +func (s *sink) WithValues(kv ...any) logr.LogSink { n := len(s.values) out := *s out.values = append(out.values[:n:n], kv...) diff --git a/internal/logging/logrus_test.go b/internal/logging/logrus_test.go index 3e73193d1a..1bbf9efc29 100644 --- a/internal/logging/logrus_test.go +++ b/internal/logging/logrus_test.go @@ -12,7 +12,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/pkg/errors" + "github.com/pkg/errors" //nolint:depguard // This is testing the logging of stack frames. "gotest.tools/v3/assert" ) diff --git a/internal/naming/annotations.go b/internal/naming/annotations.go index fa53a458fb..ec04eb0e9a 100644 --- a/internal/naming/annotations.go +++ b/internal/naming/annotations.go @@ -70,6 +70,11 @@ const ( // touch cloud-based backups. AuthorizeBackupRemovalAnnotation = annotationPrefix + "authorizeBackupRemoval" + // Used from Kubernetes v1.21+ to define a default container used when the + // `-c` flag is not passed. + // --https://kubernetes.io/docs/reference/labels-annotations-taints/#kubectl-kubernetes-io-default-container + DefaultContainerAnnotation = "kubectl.kubernetes.io/default-container" + // K8SPG-712 // OverrideConfigAnnotation is an annotation used to prevent the controller from reconciling // ConfigMaps when a user wants to manually override their contents. When this annotation diff --git a/internal/patroni/api_test.go b/internal/patroni/api_test.go index f99eccc6bd..3bd52e202f 100644 --- a/internal/patroni/api_test.go +++ b/internal/patroni/api_test.go @@ -243,7 +243,7 @@ func TestExecutorGetTimeline(t *testing.T) { tl, actual := Executor(func( _ context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string, ) error { - stderr.Write([]byte(`no luck`)) + _, _ = stderr.Write([]byte(`no luck`)) return nil }).GetTimeline(context.Background()) @@ -255,7 +255,7 @@ func TestExecutorGetTimeline(t *testing.T) { tl, actual := Executor(func( _ context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string, ) error { - stdout.Write([]byte(`no luck`)) + _, _ = stdout.Write([]byte(`no luck`)) return nil }).GetTimeline(context.Background()) @@ -267,7 +267,7 @@ func TestExecutorGetTimeline(t *testing.T) { tl, actual := Executor(func( _ context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string, ) error { - stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) + _, _ = stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) return nil }).GetTimeline(context.Background()) @@ -279,7 +279,7 @@ func TestExecutorGetTimeline(t *testing.T) { tl, actual := Executor(func( _ context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string, ) error { - stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-67mc-0", "Host": "hippo-instance1-67mc-0.hippo-pods", "Role": "Leader", "State": "running", "TL": 4}, {"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) + _, _ = stdout.Write([]byte(`[{"Cluster": "hippo-ha", "Member": "hippo-instance1-67mc-0", "Host": "hippo-instance1-67mc-0.hippo-pods", "Role": "Leader", "State": "running", "TL": 4}, {"Cluster": "hippo-ha", "Member": "hippo-instance1-ltcf-0", "Host": "hippo-instance1-ltcf-0.hippo-pods", "Role": "Replica", "State": "running", "TL": 4, "Lag in MB": 0}]`)) return nil }).GetTimeline(context.Background()) diff --git a/internal/patroni/config_test.go b/internal/patroni/config_test.go index d93a983617..4209cc0781 100644 --- a/internal/patroni/config_test.go +++ b/internal/patroni/config_test.go @@ -466,8 +466,8 @@ func TestDynamicConfiguration(t *testing.T) { }, }, hbas: postgres.HBAs{ - Default: []postgres.HostBasedAuthentication{ - *postgres.NewHBA().Local().Method("peer"), + Default: []*postgres.HostBasedAuthentication{ + postgres.NewHBA().Local().Method("peer"), }, }, expected: map[string]any{ @@ -491,8 +491,8 @@ func TestDynamicConfiguration(t *testing.T) { }, }, hbas: postgres.HBAs{ - Default: []postgres.HostBasedAuthentication{ - *postgres.NewHBA().Local().Method("peer"), + Default: []*postgres.HostBasedAuthentication{ + postgres.NewHBA().Local().Method("peer"), }, }, expected: map[string]any{ @@ -516,8 +516,8 @@ func TestDynamicConfiguration(t *testing.T) { }, }, hbas: postgres.HBAs{ - Mandatory: []postgres.HostBasedAuthentication{ - *postgres.NewHBA().Local().Method("peer"), + Mandatory: []*postgres.HostBasedAuthentication{ + postgres.NewHBA().Local().Method("peer"), }, }, expected: map[string]any{ @@ -542,8 +542,8 @@ func TestDynamicConfiguration(t *testing.T) { }, }, hbas: postgres.HBAs{ - Mandatory: []postgres.HostBasedAuthentication{ - *postgres.NewHBA().Local().Method("peer"), + Mandatory: []*postgres.HostBasedAuthentication{ + postgres.NewHBA().Local().Method("peer"), }, }, expected: map[string]any{ @@ -708,24 +708,6 @@ func TestDynamicConfiguration(t *testing.T) { }, }, }, - { - name: "pg version 10", - cluster: &v1beta1.PostgresCluster{ - Spec: v1beta1.PostgresClusterSpec{ - PostgresVersion: 10, - }, - }, - expected: map[string]any{ - "loop_wait": int32(10), - "ttl": int32(30), - "postgresql": map[string]any{ - "parameters": map[string]any{}, - "pg_hba": []string{}, - "use_pg_rewind": false, - "use_slots": false, - }, - }, - }, { name: "tde enabled", cluster: &v1beta1.PostgresCluster{ diff --git a/internal/pgadmin/config.go b/internal/pgadmin/config.go index 1d1fbf62de..f7169b69e0 100644 --- a/internal/pgadmin/config.go +++ b/internal/pgadmin/config.go @@ -160,7 +160,7 @@ if os.path.isfile('` + ldapPasswordAbsolutePath + `'): // systemSettings returns pgAdmin settings as a value that can be marshaled to JSON. func systemSettings(spec *v1beta1.PGAdminPodSpec) map[string]interface{} { - settings := *spec.Config.Settings.DeepCopy() + settings := spec.Config.Settings.DeepCopy() if settings == nil { settings = make(map[string]interface{}) } diff --git a/internal/pgbackrest/config.go b/internal/pgbackrest/config.go index fcc6d9aaba..9909754204 100644 --- a/internal/pgbackrest/config.go +++ b/internal/pgbackrest/config.go @@ -9,6 +9,7 @@ import ( "fmt" "strconv" "strings" + "time" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -172,96 +173,121 @@ func MakePGBackrestLogDir(template *corev1.PodTemplateSpec, // - Renames the data directory as needed to bootstrap the cluster using the restored database. // This ensures compatibility with the "existing" bootstrap method that is included in the // Patroni config when bootstrapping a cluster using an existing data directory. -func RestoreCommand(pgdata, hugePagesSetting, fetchKeyCommand string, tablespaceVolumes []*corev1.PersistentVolumeClaim, args ...string) []string { - - // After pgBackRest restores files, PostgreSQL starts in recovery to finish - // replaying WAL files. "hot_standby" is "on" (by default) so we can detect - // when recovery has finished. In that mode, some parameters cannot be - // smaller than they were when PostgreSQL was backed up. Configure them to - // match the values reported by "pg_controldata". Those parameters are also - // written to WAL files and may change during recovery. When they increase, - // PostgreSQL exits and we reconfigure and restart it. - // For PG14, when some parameters from WAL require a restart, the behavior is - // to pause unless a restart is requested. For this edge case, we run a CASE - // query to check - // (a) if the instance is in recovery; - // (b) if so, if the WAL replay is paused; - // (c) if so, to unpause WAL replay, allowing our expected behavior to resume. - // A note on the PostgreSQL code: we cast `pg_catalog.pg_wal_replay_resume()` as text - // because that method returns a void (which is a non-NULL but empty result). When - // that void is cast as a string, it is an '' - // - https://www.postgresql.org/docs/current/hot-standby.html - // - https://www.postgresql.org/docs/current/app-pgcontroldata.html +func RestoreCommand(pgdata, hugePagesSetting, fetchKeyCommand string, _ []*corev1.PersistentVolumeClaim, args ...string) []string { + ps := postgres.NewParameterSet() + ps.Add("data_directory", pgdata) + ps.Add("huge_pages", hugePagesSetting) - // The postmaster.pid file is removed, if it exists, before attempting a restore. - // This allows the restore to be tried more than once without the causing an - // error due to the presence of the file in subsequent attempts. + // Keep history and WAL files until the cluster starts with its normal + // archiving enabled. + ps.Add("archive_command", "false -- store WAL files locally for now") + ps.Add("archive_mode", "on") - // The 'pg_ctl' timeout is set to a very large value (1 year) to ensure there - // are no timeouts when starting or stopping Postgres. - - tablespaceCmd := "" - for _, tablespaceVolume := range tablespaceVolumes { - tablespaceCmd = tablespaceCmd + fmt.Sprintf( - "\ninstall --directory --mode=0700 '/tablespaces/%s/data'", - tablespaceVolume.Labels[naming.LabelData]) - } + // Enable "hot_standby" so we can connect to Postgres and observe its + // progress during recovery. + ps.Add("hot_standby", "on") - // If the fetch key command is not empty, save the GUC variable and value - // to a new string. - var ekc string if fetchKeyCommand != "" { - ekc = ` -encryption_key_command = '` + fetchKeyCommand + `'` + ps.Add("encryption_key_command", fetchKeyCommand) } - restoreScript := `declare -r pgdata="$1" opts="$2" -install --directory --mode=0700 "${pgdata}"` + tablespaceCmd + ` -rm -f "${pgdata}/postmaster.pid" -bash -xc "pgbackrest restore ${opts}" -rm -f "${pgdata}/patroni.dynamic.json" -export PGDATA="${pgdata}" PGHOST='/tmp' - -until [[ "${recovery=}" == 'f' ]]; do -if [[ -z "${recovery}" ]]; then -control=$(pg_controldata) -read -r max_conn <<< "${control##*max_connections setting:}" -read -r max_lock <<< "${control##*max_locks_per_xact setting:}" -read -r max_ptxn <<< "${control##*max_prepared_xacts setting:}" -read -r max_work <<< "${control##*max_worker_processes setting:}" -echo > /tmp/pg_hba.restore.conf 'local all "postgres" peer' -cat > /tmp/postgres.restore.conf <> /tmp/postgres.restore.conf "max_wal_senders = '${max_wals}'" -fi - -pg_ctl start --silent --timeout=31536000 --wait --options='--config-file=/tmp/postgres.restore.conf' -fi - -recovery=$(psql -Atc "SELECT CASE - WHEN NOT pg_catalog.pg_is_in_recovery() THEN false - WHEN NOT pg_catalog.pg_is_wal_replay_paused() THEN true - ELSE pg_catalog.pg_wal_replay_resume()::text = '' -END recovery" && sleep 1) ||: -done - -pg_ctl stop --silent --wait --timeout=31536000 -mv "${pgdata}" "${pgdata}_bootstrap"` - - return append([]string{"bash", "-ceu", "--", restoreScript, "-", pgdata}, args...) + configure := strings.Join([]string{ + // With "hot_standby" on, some parameters cannot be smaller than they were + // when Postgres was backed up. Configure these to match values reported by + // "pg_controldata" before starting Postgres. These parameters are also + // written to WAL files and may change during recovery. When they increase, + // Postgres exits and we reconfigure it here. + // - https://www.postgresql.org/docs/current/app-pgcontroldata.html + `control=$(LC_ALL=C pg_controldata)`, + `read -r max_conn <<< "${control##*max_connections setting:}"`, + `read -r max_lock <<< "${control##*max_locks_per_xact setting:}"`, + `read -r max_ptxn <<< "${control##*max_prepared_xacts setting:}"`, + `read -r max_work <<< "${control##*max_worker_processes setting:}"`, + + // During recovery, only allow connections over the the domain socket. + `echo > /tmp/pg_hba.restore.conf 'local all "postgres" peer'`, + + // Combine parameters from Go with those detected in Bash. + `cat > /tmp/postgres.restore.conf <<'EOF'`, ps.String(), `EOF`, + `cat >> /tmp/postgres.restore.conf <> /tmp/postgres.restore.conf "max_wal_senders = '${max_wals}'"`, + `fi`, + + // TODO(sockets): PostgreSQL v14 is able to connect over abstract sockets in the network namespace. + `PGHOST=$([[ "${version}" -ge 14 ]] && echo '/tmp' || echo '/tmp')`, + `echo >> /tmp/postgres.restore.conf "unix_socket_directories = '${PGHOST}'"`, + }, "\n") + + script := strings.Join([]string{ + `declare -r PGDATA="$1" opts="$2"; export PGDATA PGHOST`, + + // Remove any "postmaster.pid" file leftover from a prior failure. + `rm -f "${PGDATA}/postmaster.pid"`, + + // Run the restore and print its arguments. + `bash -xc "pgbackrest restore ${opts}"`, + + // Ignore any Patroni settings present in the backup. + `rm -f "${PGDATA}/patroni.dynamic.json"`, + + // By default, pg_ctl waits 60 seconds for Postgres to stop or start. + // We want to be certain when Postgres is running or not, so we use + // a very large timeout (365 days) to effectively wait forever. With + // this, the result of "pg_ctl --wait" indicates the state of Postgres. + // - https://www.postgresql.org/docs/current/app-pg-ctl.html + fmt.Sprintf(`export PGCTLTIMEOUT=%d`, 365*24*time.Hour/time.Second), + + // Configure and start Postgres until we can see that it has finished + // replaying WAL. + // + // PostgreSQL v13 and earlier exit when they need reconfiguration with + // "hot_standby" on. This can cause pg_ctl to fail, so we compare the + // LSN from before and after calling it. If the LSN changed, Postgres + // ran and was able to replay WAL before exiting. In that case, configure + // Postgres and start it again to see if it can make more progress. + // + // If Postgres exits after pg_ctl succeeds, psql returns nothing which + // resets the "recovering" variable. Configure Postgres and start it again. + `until [[ "${recovering=}" == 'f' ]]; do`, + ` if [[ -z "${recovering}" ]]; then`, configure, + ` read -r stopped <<< "${control##*recovery ending location:}"`, + ` pg_ctl start --silent --wait --options='-c config_file=/tmp/postgres.restore.conf' || failed=$?`, + ` [[ "${started-}" == "${stopped}" && -n "${failed-}" ]] && exit "${failed}"`, + ` started="${stopped}" && [[ -n "${failed-}" ]] && failed= && continue`, + ` fi`, + // Ask Postgres if it is still recovering. PostgreSQL v14 pauses when it + // needs reconfiguration with "hot_standby" on, and resuming replay causes + // it to exit like prior versions. + // - https://www.postgresql.org/docs/current/hot-standby.html + // + // NOTE: "pg_wal_replay_resume()" returns void which cannot be compared to + // null. Instead, cast it to text and compare that for a boolean result. + ` recovering=$(psql -Atc "SELECT CASE`, + ` WHEN NOT pg_catalog.pg_is_in_recovery() THEN false`, + ` WHEN NOT pg_catalog.pg_is_wal_replay_paused() THEN true`, + ` ELSE pg_catalog.pg_wal_replay_resume()::text = ''`, + ` END" && sleep 1) ||:`, + `done`, + + // Replay is done. Stop Postgres gracefully and move the data directory + // into position for our Patroni bootstrap method. + `pg_ctl stop --silent --wait`, + `mv "${PGDATA}" "${PGDATA}_bootstrap"`, + }, "\n") + + return append([]string{"bash", "-ceu", "--", script, "-", pgdata}, args...) } // DedicatedSnapshotVolumeRestoreCommand returns the command for performing a pgBackRest delta restore diff --git a/internal/pgbackrest/config_test.go b/internal/pgbackrest/config_test.go index 7b782cb7c6..bc69f564b6 100644 --- a/internal/pgbackrest/config_test.go +++ b/internal/pgbackrest/config_test.go @@ -13,13 +13,12 @@ import ( "testing" "gotest.tools/v3/assert" - "gotest.tools/v3/assert/cmp" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "sigs.k8s.io/yaml" "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/internal/naming" + "github.com/percona/percona-postgresql-operator/internal/testing/cmp" "github.com/percona/percona-postgresql-operator/internal/testing/require" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -217,13 +216,13 @@ pg1-socket-path = /tmp/postgres []string{"some-instance"}) assert.Assert(t, - strings.Contains(configmap.Data["pgbackrest_instance.conf"], + cmp.Contains(configmap.Data["pgbackrest_instance.conf"], "archive-header-check = n")) assert.Assert(t, - strings.Contains(configmap.Data["pgbackrest_instance.conf"], + cmp.Contains(configmap.Data["pgbackrest_instance.conf"], "page-header-check = n")) assert.Assert(t, - strings.Contains(configmap.Data["pgbackrest_instance.conf"], + cmp.Contains(configmap.Data["pgbackrest_instance.conf"], "pg-version-force")) cluster.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{ @@ -238,13 +237,13 @@ pg1-socket-path = /tmp/postgres []string{"some-instance"}) assert.Assert(t, - strings.Contains(configmap.Data["pgbackrest_repo.conf"], + cmp.Contains(configmap.Data["pgbackrest_repo.conf"], "archive-header-check = n")) assert.Assert(t, - strings.Contains(configmap.Data["pgbackrest_repo.conf"], + cmp.Contains(configmap.Data["pgbackrest_repo.conf"], "page-header-check = n")) assert.Assert(t, - strings.Contains(configmap.Data["pgbackrest_repo.conf"], + cmp.Contains(configmap.Data["pgbackrest_repo.conf"], "pg-version-force")) }) } @@ -327,10 +326,8 @@ func TestReloadCommand(t *testing.T) { } func TestReloadCommandPrettyYAML(t *testing.T) { - b, err := yaml.Marshal(reloadCommand("any", true)) - assert.NilError(t, err) - assert.Assert(t, strings.Contains(string(b), "\n- |"), - "expected literal block scalar, got:\n%s", b) + assert.Assert(t, cmp.MarshalContains(reloadCommand("any", true), "\n- |"), + "expected literal block scalar") } func TestRestoreCommand(t *testing.T) { @@ -355,19 +352,21 @@ func TestRestoreCommand(t *testing.T) { } func TestRestoreCommandPrettyYAML(t *testing.T) { - b, err := yaml.Marshal(RestoreCommand("/dir", "try", "", nil, "--options")) - - assert.NilError(t, err) - assert.Assert(t, strings.Contains(string(b), "\n- |"), - "expected literal block scalar, got:\n%s", b) + assert.Assert(t, + cmp.MarshalContains( + RestoreCommand("/dir", "try", "", nil, "--options"), + "\n- |", + ), + "expected literal block scalar") } func TestRestoreCommandTDE(t *testing.T) { - b, err := yaml.Marshal(RestoreCommand("/dir", "try", "echo testValue", nil, "--options")) - - assert.NilError(t, err) - assert.Assert(t, strings.Contains(string(b), "encryption_key_command = 'echo testValue'"), - "expected encryption_key_command setting, got:\n%s", b) + assert.Assert(t, + cmp.MarshalContains( + RestoreCommand("/dir", "try", "echo testValue", nil, "--options"), + "encryption_key_command = 'echo testValue'", + ), + "expected encryption_key_command setting") } func TestDedicatedSnapshotVolumeRestoreCommand(t *testing.T) { @@ -392,11 +391,12 @@ func TestDedicatedSnapshotVolumeRestoreCommand(t *testing.T) { } func TestDedicatedSnapshotVolumeRestoreCommandPrettyYAML(t *testing.T) { - b, err := yaml.Marshal(DedicatedSnapshotVolumeRestoreCommand("/dir", "--options")) - - assert.NilError(t, err) - assert.Assert(t, strings.Contains(string(b), "\n- |"), - "expected literal block scalar, got:\n%s", b) + assert.Assert(t, + cmp.MarshalContains( + DedicatedSnapshotVolumeRestoreCommand("/dir", "--options"), + "\n- |", + ), + "expected literal block scalar") } func TestServerConfig(t *testing.T) { diff --git a/internal/pgbouncer/postgres.go b/internal/pgbouncer/postgres.go index adf0b9b885..4f9a651238 100644 --- a/internal/pgbouncer/postgres.go +++ b/internal/pgbouncer/postgres.go @@ -40,7 +40,7 @@ func sqlAuthenticationQuery(sqlFunctionName string, exposeSuperusers bool) strin // No replicators. `NOT pg_authid.rolreplication`, // Not the PgBouncer role itself. - `pg_authid.rolname <> ` + util.SQLQuoteLiteral(postgresqlUser), + `pg_authid.rolname <> ` + postgres.QuoteLiteral(postgresqlUser), // Those without a password expiration or an expiration in the future. `(pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)`, } @@ -57,7 +57,7 @@ func sqlAuthenticationQuery(sqlFunctionName string, exposeSuperusers bool) strin return strings.TrimSpace(` CREATE OR REPLACE FUNCTION ` + sqlFunctionName + `(username TEXT) -RETURNS TABLE(username TEXT, password TEXT) AS ` + util.SQLQuoteLiteral(` +RETURNS TABLE(username TEXT, password TEXT) AS ` + postgres.QuoteLiteral(` SELECT rolname::TEXT, rolpassword::TEXT FROM pg_catalog.pg_authid WHERE pg_authid.rolname = $1 @@ -219,14 +219,14 @@ func generatePassword() (plaintext, verifier string, err error) { return } -func postgresqlHBAs() []postgres.HostBasedAuthentication { +func postgresqlHBAs() []*postgres.HostBasedAuthentication { // PgBouncer must connect over TLS using a SCRAM password. Other network // connections are forbidden. // - https://www.postgresql.org/docs/current/auth-pg-hba-conf.html // - https://www.postgresql.org/docs/current/auth-password.html - return []postgres.HostBasedAuthentication{ - *postgres.NewHBA().User(postgresqlUser).TLS().Method("scram-sha-256"), - *postgres.NewHBA().User(postgresqlUser).TCP().Method("reject"), + return []*postgres.HostBasedAuthentication{ + postgres.NewHBA().User(postgresqlUser).TLS().Method("scram-sha-256"), + postgres.NewHBA().User(postgresqlUser).TCP().Method("reject"), } } diff --git a/internal/pgbouncer/postgres_test.go b/internal/pgbouncer/postgres_test.go index e3b62dde4e..4742950330 100644 --- a/internal/pgbouncer/postgres_test.go +++ b/internal/pgbouncer/postgres_test.go @@ -19,14 +19,14 @@ import ( func TestSQLAuthenticationQuery(t *testing.T) { assert.Equal(t, sqlAuthenticationQuery("some.fn_name", false), `CREATE OR REPLACE FUNCTION some.fn_name(username TEXT) -RETURNS TABLE(username TEXT, password TEXT) AS ' +RETURNS TABLE(username TEXT, password TEXT) AS E' SELECT rolname::TEXT, rolpassword::TEXT FROM pg_catalog.pg_authid WHERE pg_authid.rolname = $1 AND pg_authid.rolcanlogin AND NOT pg_authid.rolsuper AND NOT pg_authid.rolreplication - AND pg_authid.rolname <> ''_crunchypgbouncer'' + AND pg_authid.rolname <> E''_crunchypgbouncer'' AND (pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)' LANGUAGE SQL STABLE SECURITY DEFINER;`) } @@ -34,13 +34,13 @@ LANGUAGE SQL STABLE SECURITY DEFINER;`) func TestSQLAuthenticationQueryWithExposedSuperusers(t *testing.T) { assert.Equal(t, sqlAuthenticationQuery("some.fn_name", true), `CREATE OR REPLACE FUNCTION some.fn_name(username TEXT) -RETURNS TABLE(username TEXT, password TEXT) AS ' +RETURNS TABLE(username TEXT, password TEXT) AS E' SELECT rolname::TEXT, rolpassword::TEXT FROM pg_catalog.pg_authid WHERE pg_authid.rolname = $1 AND pg_authid.rolcanlogin AND (NOT pg_authid.rolreplication OR pg_authid.rolname = ''postgres'') - AND pg_authid.rolname <> ''_crunchypgbouncer'' + AND pg_authid.rolname <> E''_crunchypgbouncer'' AND (pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)' LANGUAGE SQL STABLE SECURITY DEFINER;`) } @@ -164,14 +164,14 @@ REVOKE ALL PRIVILEGES GRANT USAGE ON SCHEMA :"namespace" TO :"username"; CREATE OR REPLACE FUNCTION :"namespace".get_auth(username TEXT) -RETURNS TABLE(username TEXT, password TEXT) AS ' +RETURNS TABLE(username TEXT, password TEXT) AS E' SELECT rolname::TEXT, rolpassword::TEXT FROM pg_catalog.pg_authid WHERE pg_authid.rolname = $1 AND pg_authid.rolcanlogin AND NOT pg_authid.rolsuper AND NOT pg_authid.rolreplication - AND pg_authid.rolname <> ''_crunchypgbouncer'' + AND pg_authid.rolname <> E''_crunchypgbouncer'' AND (pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)' LANGUAGE SQL STABLE SECURITY DEFINER; REVOKE ALL PRIVILEGES @@ -230,13 +230,13 @@ REVOKE ALL PRIVILEGES GRANT USAGE ON SCHEMA :"namespace" TO :"username"; CREATE OR REPLACE FUNCTION :"namespace".get_auth(username TEXT) -RETURNS TABLE(username TEXT, password TEXT) AS ' +RETURNS TABLE(username TEXT, password TEXT) AS E' SELECT rolname::TEXT, rolpassword::TEXT FROM pg_catalog.pg_authid WHERE pg_authid.rolname = $1 AND pg_authid.rolcanlogin AND (NOT pg_authid.rolreplication OR pg_authid.rolname = ''postgres'') - AND pg_authid.rolname <> ''_crunchypgbouncer'' + AND pg_authid.rolname <> E''_crunchypgbouncer'' AND (pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)' LANGUAGE SQL STABLE SECURITY DEFINER; REVOKE ALL PRIVILEGES diff --git a/internal/pgbouncer/reconcile_test.go b/internal/pgbouncer/reconcile_test.go index 0e88177461..db0730d188 100644 --- a/internal/pgbouncer/reconcile_test.go +++ b/internal/pgbouncer/reconcile_test.go @@ -500,6 +500,6 @@ func TestPostgreSQL(t *testing.T) { Mandatory: postgresqlHBAs(), }, // postgres.HostBasedAuthentication has unexported fields. Call String() to compare. - gocmp.Transformer("", postgres.HostBasedAuthentication.String)) + gocmp.Transformer("", (*postgres.HostBasedAuthentication).String)) }) } diff --git a/internal/pgmonitor/postgres.go b/internal/pgmonitor/postgres.go index 10f0618d73..6af8515e9d 100644 --- a/internal/pgmonitor/postgres.go +++ b/internal/pgmonitor/postgres.go @@ -25,9 +25,9 @@ func PostgreSQLHBAs(inCluster *v1beta1.PostgresCluster, outHBAs *postgres.HBAs) if ExporterEnabled(inCluster) { // Limit the monitoring user to local connections using SCRAM. outHBAs.Mandatory = append(outHBAs.Mandatory, - *postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("127.0.0.0/8"), - *postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("::1/128"), - *postgres.NewHBA().TCP().User(MonitoringUser).Method("reject")) + postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("127.0.0.0/8"), + postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("::1/128"), + postgres.NewHBA().TCP().User(MonitoringUser).Method("reject")) } } diff --git a/internal/pmm/hba.go b/internal/pmm/hba.go index 628f6b7cc7..1afea911ee 100644 --- a/internal/pmm/hba.go +++ b/internal/pmm/hba.go @@ -15,7 +15,7 @@ const ( func PostgreSQLHBAs(inCluster *v1beta1.PostgresCluster, outHBAs *postgres.HBAs) { // Limit the monitoring user to local connections using SCRAM. outHBAs.Mandatory = append(outHBAs.Mandatory, - *postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("127.0.0.0/8"), - *postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("::1/128"), - *postgres.NewHBA().TCP().User(MonitoringUser).Method("reject")) + postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("127.0.0.0/8"), + postgres.NewHBA().TCP().User(MonitoringUser).Method("scram-sha-256").Network("::1/128"), + postgres.NewHBA().TCP().User(MonitoringUser).Method("reject")) } diff --git a/internal/postgres/hba.go b/internal/postgres/hba.go index 343c9544b5..e245f81f4a 100644 --- a/internal/postgres/hba.go +++ b/internal/postgres/hba.go @@ -12,31 +12,31 @@ import ( // NewHBAs returns HostBasedAuthentication records required by this package. func NewHBAs() HBAs { return HBAs{ - Mandatory: []HostBasedAuthentication{ + Mandatory: []*HostBasedAuthentication{ // The "postgres" superuser must always be able to connect locally. - *NewHBA().Local().User("postgres").Method("peer"), + NewHBA().Local().User("postgres").Method("peer"), // The replication user must always connect over TLS using certificate // authentication. Patroni also connects to the "postgres" database // when calling `pg_rewind`. // - https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-AUTHENTICATION - *NewHBA().TLS().User(ReplicationUser).Method("cert").Replication(), - *NewHBA().TLS().User(ReplicationUser).Method("cert").Database("postgres"), - *NewHBA().TCP().User(ReplicationUser).Method("reject"), + NewHBA().TLS().User(ReplicationUser).Method("cert").Replication(), + NewHBA().TLS().User(ReplicationUser).Method("cert").Database("postgres"), + NewHBA().TCP().User(ReplicationUser).Method("reject"), }, - Default: []HostBasedAuthentication{ + Default: []*HostBasedAuthentication{ // Allow TLS connections to any database using passwords. The "md5" // authentication method automatically verifies passwords encrypted // using either MD5 or SCRAM-SHA-256. // - https://www.postgresql.org/docs/current/auth-password.html - *NewHBA().TLS().Method("md5"), + NewHBA().TLS().Method("md5"), }, } } // HBAs is a pairing of HostBasedAuthentication records. -type HBAs struct{ Mandatory, Default []HostBasedAuthentication } +type HBAs struct{ Mandatory, Default []*HostBasedAuthentication } // HostBasedAuthentication represents a single record for pg_hba.conf. // - https://www.postgresql.org/docs/current/auth-pg-hba-conf.html @@ -49,7 +49,7 @@ func NewHBA() *HostBasedAuthentication { return new(HostBasedAuthentication).AllDatabases().AllNetworks().AllUsers() } -func (HostBasedAuthentication) quote(value string) string { +func (*HostBasedAuthentication) quote(value string) string { return `"` + strings.ReplaceAll(value, `"`, `""`) + `"` } @@ -155,7 +155,7 @@ func (hba *HostBasedAuthentication) User(name string) *HostBasedAuthentication { } // String returns hba formatted for the pg_hba.conf file without a newline. -func (hba HostBasedAuthentication) String() string { +func (hba *HostBasedAuthentication) String() string { if hba.origin == "local" { return strings.TrimSpace(fmt.Sprintf("local %s %s %s %s", hba.database, hba.user, hba.method, hba.options)) diff --git a/internal/postgres/hba_test.go b/internal/postgres/hba_test.go index 212c4ad5d0..34469a7f13 100644 --- a/internal/postgres/hba_test.go +++ b/internal/postgres/hba_test.go @@ -14,7 +14,7 @@ import ( ) func TestNewHBAs(t *testing.T) { - matches := func(actual []HostBasedAuthentication, expected string) cmp.Comparison { + matches := func(actual []*HostBasedAuthentication, expected string) cmp.Comparison { printed := make([]string, len(actual)) for i := range actual { printed[i] = actual[i].String() diff --git a/internal/postgres/parameters.go b/internal/postgres/parameters.go index 434d9fd1dd..bbb80b0ac1 100644 --- a/internal/postgres/parameters.go +++ b/internal/postgres/parameters.go @@ -5,6 +5,8 @@ package postgres import ( + "fmt" + "slices" "strings" ) @@ -65,7 +67,7 @@ func NewParameterSet() *ParameterSet { } // AsMap returns a copy of ps as a map. -func (ps ParameterSet) AsMap() map[string]string { +func (ps *ParameterSet) AsMap() map[string]string { out := make(map[string]string, len(ps.values)) for name, value := range ps.values { out[name] = value @@ -102,25 +104,43 @@ func (ps *ParameterSet) AppendToList(name string, value ...string) { } // Get returns the value of parameter name and whether or not it was present in ps. -func (ps ParameterSet) Get(name string) (string, bool) { +func (ps *ParameterSet) Get(name string) (string, bool) { value, ok := ps.values[ps.normalize(name)] return value, ok } // Has returns whether or not parameter name is present in ps. -func (ps ParameterSet) Has(name string) bool { +func (ps *ParameterSet) Has(name string) bool { _, ok := ps.Get(name) return ok } -func (ParameterSet) normalize(name string) string { +func (*ParameterSet) normalize(name string) string { // All parameter names are case-insensitive. // -- https://www.postgresql.org/docs/current/config-setting.html return strings.ToLower(name) } // Value returns empty string or the value of parameter name if it is present in ps. -func (ps ParameterSet) Value(name string) string { +func (ps *ParameterSet) Value(name string) string { value, _ := ps.Get(name) return value } + +func (ps *ParameterSet) String() string { + keys := make([]string, 0, len(ps.values)) + for k := range ps.values { + keys = append(keys, k) + } + + slices.Sort(keys) + + var b strings.Builder + for _, k := range keys { + _, _ = fmt.Fprintf(&b, "%s = '%s'\n", k, escapeParameterQuotes(ps.values[k])) + } + return b.String() +} + +// escapeParameterQuotes is used by [ParameterSet.String]. +var escapeParameterQuotes = strings.NewReplacer(`'`, `''`).Replace diff --git a/internal/postgres/parameters_test.go b/internal/postgres/parameters_test.go index c6228d7958..0720d8b42a 100644 --- a/internal/postgres/parameters_test.go +++ b/internal/postgres/parameters_test.go @@ -56,6 +56,10 @@ func TestParameterSet(t *testing.T) { ps2.Add("x", "n") assert.Assert(t, ps2.Value("x") != ps.Value("x")) + + assert.DeepEqual(t, ps.String(), ``+ + `abc = 'j''l'`+"\n"+ + `x = 'z'`+"\n") } func TestParameterSetAppendToList(t *testing.T) { diff --git a/internal/postgres/sql.go b/internal/postgres/sql.go new file mode 100644 index 0000000000..8bef9aaaa6 --- /dev/null +++ b/internal/postgres/sql.go @@ -0,0 +1,22 @@ +// Copyright 2021 - 2024 Crunchy Data Solutions, Inc. +// +// SPDX-License-Identifier: Apache-2.0 + +package postgres + +import "strings" + +// escapeLiteral is called by QuoteLiteral to add backslashes before special +// characters of the "escape" string syntax. Double quote marks to escape them +// regardless of the "backslash_quote" parameter. +var escapeLiteral = strings.NewReplacer(`'`, `''`, `\`, `\\`).Replace + +// QuoteLiteral escapes v so it can be safely used as a literal (or constant) +// in an SQL statement. +func QuoteLiteral(v string) string { + // Use the "escape" syntax to ensure that backslashes behave consistently regardless + // of the "standard_conforming_strings" parameter. Include a space before so + // the "E" cannot change the meaning of an adjacent SQL keyword or identifier. + // - https://www.postgresql.org/docs/current/sql-syntax-lexical.html + return ` E'` + escapeLiteral(v) + `'` +} diff --git a/internal/postgres/sql_test.go b/internal/postgres/sql_test.go new file mode 100644 index 0000000000..fdca26760c --- /dev/null +++ b/internal/postgres/sql_test.go @@ -0,0 +1,16 @@ +// Copyright 2021 - 2024 Crunchy Data Solutions, Inc. +// +// SPDX-License-Identifier: Apache-2.0 + +package postgres + +import ( + "testing" + + "gotest.tools/v3/assert" +) + +func TestQuoteLiteral(t *testing.T) { + assert.Equal(t, QuoteLiteral(``), ` E''`) + assert.Equal(t, QuoteLiteral(`ab"cd\ef'gh`), ` E'ab"cd\\ef''gh'`) +} diff --git a/internal/postgres/versions.go b/internal/postgres/versions.go new file mode 100644 index 0000000000..8a5e544040 --- /dev/null +++ b/internal/postgres/versions.go @@ -0,0 +1,26 @@ +// Copyright 2021 - 2024 Crunchy Data Solutions, Inc. +// +// SPDX-License-Identifier: Apache-2.0 + +package postgres + +import "time" + +// https://www.postgresql.org/support/versioning +var finalReleaseDates = map[int]time.Time{ + 10: time.Date(2022, time.November+1, 10, 0, 0, 0, 0, time.UTC), + 11: time.Date(2023, time.November+1, +9, 0, 0, 0, 0, time.UTC), + 12: time.Date(2024, time.November+1, 14, 0, 0, 0, 0, time.UTC), + 13: time.Date(2025, time.November+1, 13, 0, 0, 0, 0, time.UTC), + 14: time.Date(2026, time.November+1, 12, 0, 0, 0, 0, time.UTC), + 15: time.Date(2027, time.November+1, 11, 0, 0, 0, 0, time.UTC), + 16: time.Date(2028, time.November+1, +9, 0, 0, 0, 0, time.UTC), + 17: time.Date(2029, time.November+1, +8, 0, 0, 0, 0, time.UTC), +} + +// ReleaseIsFinal returns whether or not t is definitively past the final +// scheduled release of a Postgres version. +func ReleaseIsFinal(majorVersion int, t time.Time) bool { + known, ok := finalReleaseDates[majorVersion] + return ok && t.After(known) +} diff --git a/internal/postgres/versions_test.go b/internal/postgres/versions_test.go new file mode 100644 index 0000000000..7d2bd96c60 --- /dev/null +++ b/internal/postgres/versions_test.go @@ -0,0 +1,34 @@ +// Copyright 2021 - 2024 Crunchy Data Solutions, Inc. +// +// SPDX-License-Identifier: Apache-2.0 + +package postgres + +import ( + "testing" + "time" + + "gotest.tools/v3/assert" +) + +func TestReleaseIsFinal(t *testing.T) { + // On November 4th, 2024, PG 10 and 11 were EOL and 12-17 were supported. + testDate, err := time.Parse("2006-Jan-02", "2024-Nov-04") + assert.NilError(t, err) + assert.Check(t, ReleaseIsFinal(10, testDate)) + assert.Check(t, ReleaseIsFinal(11, testDate)) + assert.Check(t, !ReleaseIsFinal(12, testDate)) + assert.Check(t, !ReleaseIsFinal(13, testDate)) + assert.Check(t, !ReleaseIsFinal(14, testDate)) + assert.Check(t, !ReleaseIsFinal(15, testDate)) + assert.Check(t, !ReleaseIsFinal(16, testDate)) + assert.Check(t, !ReleaseIsFinal(17, testDate)) + + // On December 15th, 2024 we alert that PG 12 is EOL + testDate = testDate.AddDate(0, 1, 11) + assert.Check(t, ReleaseIsFinal(12, testDate)) + + // ReleaseIsFinal covers PG versions 10 and greater. Any version not covered + // by the case statement in ReleaseIsFinal returns false + assert.Check(t, !ReleaseIsFinal(1, testDate)) +} diff --git a/internal/registration/runner.go b/internal/registration/runner.go index 19e5446aea..eb5bfe576e 100644 --- a/internal/registration/runner.go +++ b/internal/registration/runner.go @@ -181,10 +181,6 @@ func (r *Runner) Start(ctx context.Context) error { r.changed() } case <-ctx.Done(): - // https://github.com/kubernetes-sigs/controller-runtime/issues/1927 - if errors.Is(ctx.Err(), context.Canceled) { - return nil - } return ctx.Err() } } diff --git a/internal/testing/cmp/cmp.go b/internal/testing/cmp/cmp.go index 265a598064..47884777e4 100644 --- a/internal/testing/cmp/cmp.go +++ b/internal/testing/cmp/cmp.go @@ -50,6 +50,15 @@ func DeepEqual(x, y any, opts ...gocmp.Option) Comparison { return gotest.DeepEqual(x, y, opts...) } +// MarshalContains converts actual to YAML and succeeds if expected is in the result. +func MarshalContains(actual any, expected string) Comparison { + b, err := yaml.Marshal(actual) + if err != nil { + return func() gotest.Result { return gotest.ResultFromError(err) } + } + return Contains(string(b), expected) +} + // MarshalMatches converts actual to YAML and compares that to expected. func MarshalMatches(actual any, expected string) Comparison { b, err := yaml.Marshal(actual) diff --git a/internal/testing/require/kubernetes.go b/internal/testing/require/kubernetes.go index 7f8b18cca3..c8e6d61127 100644 --- a/internal/testing/require/kubernetes.go +++ b/internal/testing/require/kubernetes.go @@ -11,8 +11,8 @@ import ( goruntime "runtime" "strings" "sync" - "testing" + "golang.org/x/tools/go/packages" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/rest" @@ -22,6 +22,14 @@ import ( "github.com/percona/percona-postgresql-operator/internal/controller/runtime" ) +type TestingT interface { + assert.TestingT + Cleanup(func()) + Helper() + Name() string + SkipNow() +} + // https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest#pkg-constants var envtestVarsSet = os.Getenv("KUBEBUILDER_ASSETS") != "" || strings.EqualFold(os.Getenv("USE_EXISTING_CLUSTER"), "true") @@ -29,7 +37,7 @@ var envtestVarsSet = os.Getenv("KUBEBUILDER_ASSETS") != "" || // EnvTest returns an unstarted Environment with crds. It calls t.Skip when // the "KUBEBUILDER_ASSETS" and "USE_EXISTING_CLUSTER" environment variables // are unset. -func EnvTest(t testing.TB, crds envtest.CRDInstallOptions) *envtest.Environment { +func EnvTest(t TestingT, crds envtest.CRDInstallOptions) *envtest.Environment { t.Helper() if !envtestVarsSet { @@ -59,7 +67,7 @@ var kubernetes struct { // // Tests that call t.Parallel might share the same local API. Call t.Parallel after this // function to ensure they share. -func Kubernetes(t testing.TB) client.Client { +func Kubernetes(t TestingT) client.Client { t.Helper() _, cc := kubernetes3(t) return cc @@ -67,13 +75,13 @@ func Kubernetes(t testing.TB) client.Client { // Kubernetes2 is the same as [Kubernetes] but also returns a copy of the client // configuration. -func Kubernetes2(t testing.TB) (*rest.Config, client.Client) { +func Kubernetes2(t TestingT) (*rest.Config, client.Client) { t.Helper() env, cc := kubernetes3(t) return rest.CopyConfig(env.Config), cc } -func kubernetes3(t testing.TB) (*envtest.Environment, client.Client) { +func kubernetes3(t TestingT) (*envtest.Environment, client.Client) { t.Helper() if !envtestVarsSet { @@ -102,6 +110,18 @@ func kubernetes3(t testing.TB) (*envtest.Environment, client.Client) { base, err := filepath.Rel(filepath.Dir(caller), root) assert.NilError(t, err) + // Calculate the snapshotter module directory path relative to the project directory. + var snapshotter string + if pkgs, err := packages.Load( + &packages.Config{Mode: packages.NeedModule}, + "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1", + ); assert.Check(t, + err == nil && len(pkgs) > 0 && pkgs[0].Module != nil, "got %v\n%#v", err, pkgs, + ) { + snapshotter, err = filepath.Rel(root, pkgs[0].Module.Dir) + assert.NilError(t, err) + } + kubernetes.Lock() defer kubernetes.Unlock() @@ -110,7 +130,7 @@ func kubernetes3(t testing.TB) (*envtest.Environment, client.Client) { ErrorIfPathMissing: true, Paths: []string{ filepath.Join(base, "config", "crd", "bases"), - filepath.Join(base, "hack", "tools", "external-snapshotter", "client", "config", "crd"), + filepath.Join(base, snapshotter, "config", "crd"), }, Scheme: runtime.Scheme, }) @@ -145,7 +165,7 @@ func kubernetes3(t testing.TB) (*envtest.Environment, client.Client) { // Namespace creates a random namespace that is deleted by t.Cleanup. It calls // t.Fatal when creation fails. The caller may delete the namespace at any time. -func Namespace(t testing.TB, cc client.Client) *corev1.Namespace { +func Namespace(t TestingT, cc client.Client) *corev1.Namespace { t.Helper() // Remove / that shows up when running a sub-test diff --git a/internal/upgradecheck/header.go b/internal/upgradecheck/header.go index 63941d457c..b418691a9b 100644 --- a/internal/upgradecheck/header.go +++ b/internal/upgradecheck/header.go @@ -18,6 +18,7 @@ import ( "k8s.io/client-go/rest" crclient "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/internal/naming" @@ -57,7 +58,7 @@ func generateHeader(ctx context.Context, cfg *rest.Config, crClient crclient.Cli BridgeClustersTotal: getBridgeClusters(ctx, crClient), BuildSource: os.Getenv("BUILD_SOURCE"), DeploymentID: ensureDeploymentID(ctx, crClient), - FeatureGatesEnabled: feature.ShowGates(ctx), + FeatureGatesEnabled: feature.ShowEnabled(ctx), IsOpenShift: isOpenShift, KubernetesEnv: getServerVersion(ctx, cfg), PGOClustersTotal: getManagedClusters(ctx, crClient), @@ -128,7 +129,7 @@ func manageUpgradeCheckConfigMap(ctx context.Context, crClient crclient.Client, } } - err = applyConfigMap(ctx, crClient, cm, currentID) + err = applyConfigMap(ctx, crClient, cm, postgrescluster.ControllerName) if err != nil { log.V(1).Info("upgrade check issue: could not apply configmap", "response", err.Error()) @@ -208,11 +209,8 @@ func getServerVersion(ctx context.Context, cfg *rest.Config) string { return versionInfo.String() } -func addHeader(req *http.Request, upgradeInfo *clientUpgradeData) (*http.Request, error) { - marshaled, err := json.Marshal(upgradeInfo) - if err == nil { - upgradeInfoString := string(marshaled) - req.Header.Add(clientHeader, upgradeInfoString) - } - return req, err +func addHeader(req *http.Request, upgradeInfo *clientUpgradeData) *http.Request { + marshaled, _ := json.Marshal(upgradeInfo) + req.Header.Add(clientHeader, string(marshaled)) + return req } diff --git a/internal/upgradecheck/header_test.go b/internal/upgradecheck/header_test.go index 29d26104ee..995a9a2768 100644 --- a/internal/upgradecheck/header_test.go +++ b/internal/upgradecheck/header_test.go @@ -32,7 +32,6 @@ func TestGenerateHeader(t *testing.T) { setupDeploymentID(t) ctx := context.Background() cfg, cc := require.Kubernetes2(t) - setupNamespace(t, cc) dc, err := discovery.NewDiscoveryClientForConfig(cfg) assert.NilError(t, err) @@ -43,6 +42,7 @@ func TestGenerateHeader(t *testing.T) { t.Setenv("PGO_INSTALLER", "test") t.Setenv("PGO_INSTALLER_ORIGIN", "test-origin") + t.Setenv("PGO_NAMESPACE", require.Namespace(t, cc).Name) t.Setenv("BUILD_SOURCE", "developer") t.Run("error ensuring ID", func(t *testing.T) { @@ -136,7 +136,10 @@ func TestGenerateHeader(t *testing.T) { assert.Equal(t, len(pgoList.Items), res.PGOClustersTotal) assert.Equal(t, "1.2.3", res.PGOVersion) assert.Equal(t, server.String(), res.KubernetesEnv) - assert.Equal(t, "TablespaceVolumes=true", res.FeatureGatesEnabled) + assert.Check(t, strings.Contains( + res.FeatureGatesEnabled, + "TablespaceVolumes=true", + )) assert.Equal(t, "test", res.PGOInstaller) assert.Equal(t, "test-origin", res.PGOInstallerOrigin) assert.Equal(t, "developer", res.BuildSource) @@ -146,7 +149,7 @@ func TestGenerateHeader(t *testing.T) { func TestEnsureID(t *testing.T) { ctx := context.Background() cc := require.Kubernetes(t) - setupNamespace(t, cc) + t.Setenv("PGO_NAMESPACE", require.Namespace(t, cc).Name) t.Run("success, no id set in mem or configmap", func(t *testing.T) { deploymentID = "" @@ -282,7 +285,7 @@ func TestEnsureID(t *testing.T) { func TestManageUpgradeCheckConfigMap(t *testing.T) { ctx := context.Background() cc := require.Kubernetes(t) - setupNamespace(t, cc) + t.Setenv("PGO_NAMESPACE", require.Namespace(t, cc).Name) t.Run("no namespace given", func(t *testing.T) { ctx, calls := setupLogCapture(ctx) @@ -408,7 +411,7 @@ func TestManageUpgradeCheckConfigMap(t *testing.T) { func TestApplyConfigMap(t *testing.T) { ctx := context.Background() cc := require.Kubernetes(t) - setupNamespace(t, cc) + t.Setenv("PGO_NAMESPACE", require.Namespace(t, cc).Name) t.Run("successful create", func(t *testing.T) { cmRetrieved := &corev1.ConfigMap{} @@ -596,12 +599,11 @@ func TestAddHeader(t *testing.T) { PGOVersion: versionString, } - result, err := addHeader(req, upgradeInfo) - assert.NilError(t, err) + result := addHeader(req, upgradeInfo) header := result.Header[clientHeader] passedThroughData := &clientUpgradeData{} - err = json.Unmarshal([]byte(header[0]), passedThroughData) + err := json.Unmarshal([]byte(header[0]), passedThroughData) assert.NilError(t, err) assert.Equal(t, passedThroughData.PGOVersion, "1.2.3") diff --git a/internal/upgradecheck/helpers_test.go b/internal/upgradecheck/helpers_test.go index 159f1b1d9b..e687569e7f 100644 --- a/internal/upgradecheck/helpers_test.go +++ b/internal/upgradecheck/helpers_test.go @@ -13,8 +13,6 @@ import ( "testing" "github.com/go-logr/logr/funcr" - "gotest.tools/v3/assert" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" @@ -153,26 +151,3 @@ func setupLogCapture(ctx context.Context) (context.Context, *[]string) { }) return logging.NewContext(ctx, testlog), &calls } - -// setupNamespace creates a namespace that will be deleted by t.Cleanup. -// For upgradechecking, this namespace is set to `postgres-operator`, -// which sometimes is created by other parts of the testing apparatus, -// cf., the createnamespace call in `make check-envtest-existing`. -// When creation fails, it calls t.Fatal. The caller may delete the namespace -// at any time. -func setupNamespace(t testing.TB, cc crclient.Client) { - t.Helper() - ns := &corev1.Namespace{} - ns.Name = "postgres-operator" - ns.Labels = map[string]string{"postgres-operator-test": t.Name()} - - ctx := context.Background() - exists := &corev1.Namespace{} - assert.NilError(t, crclient.IgnoreNotFound( - cc.Get(ctx, crclient.ObjectKeyFromObject(ns), exists))) - if exists.Name != "" { - return - } - assert.NilError(t, cc.Create(ctx, ns)) - t.Cleanup(func() { assert.Check(t, crclient.IgnoreNotFound(cc.Delete(ctx, ns))) }) -} diff --git a/internal/upgradecheck/http.go b/internal/upgradecheck/http.go index 5cb337e149..0de194245e 100644 --- a/internal/upgradecheck/http.go +++ b/internal/upgradecheck/http.go @@ -77,7 +77,7 @@ func checkForUpgrades(ctx context.Context, url, versionString string, backoff wa // in case some of the checks return errors headerPayloadStruct = generateHeader(ctx, cfg, crclient, versionString, isOpenShift, registrationToken) - req, err = addHeader(req, headerPayloadStruct) + req = addHeader(req, headerPayloadStruct) } // wait.ExponentialBackoff will retry the func according to the backoff object until diff --git a/internal/upgradecheck/http_test.go b/internal/upgradecheck/http_test.go index c0391e1cfa..c50b92c41e 100644 --- a/internal/upgradecheck/http_test.go +++ b/internal/upgradecheck/http_test.go @@ -69,7 +69,7 @@ func TestCheckForUpgrades(t *testing.T) { assert.Equal(t, data.RegistrationToken, "speakFriend") assert.Equal(t, data.BridgeClustersTotal, 2) assert.Equal(t, data.PGOClustersTotal, 2) - assert.Equal(t, data.FeatureGatesEnabled, "TablespaceVolumes=true") + assert.Equal(t, data.FeatureGatesEnabled, "AutoCreateUserSchema=true,TablespaceVolumes=true") } t.Run("success", func(t *testing.T) { diff --git a/internal/util/util.go b/internal/util/util.go deleted file mode 100644 index 72634ebbc6..0000000000 --- a/internal/util/util.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2017 - 2024 Crunchy Data Solutions, Inc. -// -// SPDX-License-Identifier: Apache-2.0 - -package util - -import ( - "strings" -) - -// SQLQuoteIdentifier quotes an "identifier" (e.g. a table or a column name) to -// be used as part of an SQL statement. -// -// Any double quotes in name will be escaped. The quoted identifier will be -// case-sensitive when used in a query. If the input string contains a zero -// byte, the result will be truncated immediately before it. -// -// Implementation borrowed from lib/pq: https://github.com/lib/pq which is -// licensed under the MIT License -func SQLQuoteIdentifier(identifier string) string { - end := strings.IndexRune(identifier, 0) - - if end > -1 { - identifier = identifier[:end] - } - - return `"` + strings.Replace(identifier, `"`, `""`, -1) + `"` -} - -// SQLQuoteLiteral quotes a 'literal' (e.g. a parameter, often used to pass literal -// to DDL and other statements that do not accept parameters) to be used as part -// of an SQL statement. -// -// Any single quotes in name will be escaped. Any backslashes (i.e. "\") will be -// replaced by two backslashes (i.e. "\\") and the C-style escape identifier -// that PostgreSQL provides ('E') will be prepended to the string. -// -// Implementation borrowed from lib/pq: https://github.com/lib/pq which is -// licensed under the MIT License. Curiously, @jkatz and @cbandy were the ones -// who worked on the patch to add this, prior to being at Crunchy Data -func SQLQuoteLiteral(literal string) string { - // This follows the PostgreSQL internal algorithm for handling quoted literals - // from libpq, which can be found in the "PQEscapeStringInternal" function, - // which is found in the libpq/fe-exec.c source file: - // https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/interfaces/libpq/fe-exec.c - // - // substitute any single-quotes (') with two single-quotes ('') - literal = strings.Replace(literal, `'`, `''`, -1) - // determine if the string has any backslashes (\) in it. - // if it does, replace any backslashes (\) with two backslashes (\\) - // then, we need to wrap the entire string with a PostgreSQL - // C-style escape. Per how "PQEscapeStringInternal" handles this case, we - // also add a space before the "E" - if strings.Contains(literal, `\`) { - literal = strings.Replace(literal, `\`, `\\`, -1) - literal = ` E'` + literal + `'` - } else { - // otherwise, we can just wrap the literal with a pair of single quotes - literal = `'` + literal + `'` - } - return literal -} diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go index 61cf886e4e..39342012c3 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go @@ -26,7 +26,7 @@ type CrunchyBridgeClusterSpec struct { // Whether the cluster is protected. Protected clusters can't be destroyed until // their protected flag is removed - // +optional + // +kubebuilder:validation:Optional IsProtected bool `json:"isProtected,omitempty"` // The name of the cluster @@ -68,14 +68,14 @@ type CrunchyBridgeClusterSpec struct { // are retrieved from the Bridge API. An empty list creates no role secrets. // Removing a role from this list does NOT drop the role nor revoke their // access, but it will delete that role's secret from the kube cluster. + // +kubebuilder:validation:Optional // +listType=map // +listMapKey=name - // +optional Roles []*CrunchyBridgeClusterRoleSpec `json:"roles,omitempty"` // The name of the secret containing the API key and team id // +kubebuilder:validation:Required - Secret string `json:"secret,omitempty"` + Secret string `json:"secret"` // The amount of storage available to the cluster in gigabytes. // The amount must be an integer, followed by Gi (gibibytes) or G (gigabytes) to match Kubernetes conventions. @@ -89,9 +89,11 @@ type CrunchyBridgeClusterSpec struct { type CrunchyBridgeClusterRoleSpec struct { // Name of the role within Crunchy Bridge. // More info: https://docs.crunchybridge.com/concepts/users + // +kubebuilder:validation:Required Name string `json:"name"` // The name of the Secret that will hold the role credentials. + // +kubebuilder:validation:Required // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Type=string diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go index 201989fb50..995442b777 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go @@ -47,15 +47,15 @@ type PGBackRestJobStatus struct { type PGBackRestScheduledBackupStatus struct { // The name of the associated pgBackRest scheduled backup CronJob - // +kubebuilder:validation:Required + // +kubebuilder:validation:Optional CronJobName string `json:"cronJobName,omitempty"` // The name of the associated pgBackRest repository - // +kubebuilder:validation:Required + // +kubebuilder:validation:Optional RepoName string `json:"repo,omitempty"` // The pgBackRest backup type for this Job - // +kubebuilder:validation:Required + // +kubebuilder:validation:Optional Type string `json:"type,omitempty"` // Represents the time the manual backup Job was acknowledged by the Job controller. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go index e73ee6e7f6..0561d897aa 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go @@ -18,13 +18,8 @@ import ( type SchemalessObject map[string]any // DeepCopy creates a new SchemalessObject by copying the receiver. -func (in *SchemalessObject) DeepCopy() *SchemalessObject { - if in == nil { - return nil - } - out := new(SchemalessObject) - *out = runtime.DeepCopyJSON(*in) - return out +func (in SchemalessObject) DeepCopy() SchemalessObject { + return runtime.DeepCopyJSON(in) } type ServiceSpec struct { diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go index 96cd4da073..fdd7440947 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go @@ -15,11 +15,8 @@ import ( func TestSchemalessObjectDeepCopy(t *testing.T) { t.Parallel() - var n *SchemalessObject - assert.DeepEqual(t, n, n.DeepCopy()) - var z SchemalessObject - assert.DeepEqual(t, z, *z.DeepCopy()) + assert.DeepEqual(t, z, z.DeepCopy()) var one SchemalessObject assert.NilError(t, yaml.Unmarshal( @@ -27,31 +24,31 @@ func TestSchemalessObjectDeepCopy(t *testing.T) { )) // reflect and go-cmp agree the original and copy are equivalent. - same := *one.DeepCopy() + same := one.DeepCopy() assert.DeepEqual(t, one, same) assert.Assert(t, reflect.DeepEqual(one, same)) // Changes to the copy do not affect the original. { - change := *one.DeepCopy() + change := one.DeepCopy() change["str"] = "banana" assert.Assert(t, reflect.DeepEqual(one, same)) assert.Assert(t, !reflect.DeepEqual(one, change)) } { - change := *one.DeepCopy() + change := one.DeepCopy() change["num"] = 99 assert.Assert(t, reflect.DeepEqual(one, same)) assert.Assert(t, !reflect.DeepEqual(one, change)) } { - change := *one.DeepCopy() + change := one.DeepCopy() change["arr"].([]any)[0] = "rock" assert.Assert(t, reflect.DeepEqual(one, same)) assert.Assert(t, !reflect.DeepEqual(one, change)) } { - change := *one.DeepCopy() + change := one.DeepCopy() change["arr"] = append(change["arr"].([]any), "more") assert.Assert(t, reflect.DeepEqual(one, same)) assert.Assert(t, !reflect.DeepEqual(one, change)) diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 3d1486fb69..b741dcf28e 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -18,9 +18,9 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *APIResponses) DeepCopyInto(out *APIResponses) { *out = *in - in.Cluster.DeepCopyInto(&out.Cluster) - in.Status.DeepCopyInto(&out.Status) - in.Upgrade.DeepCopyInto(&out.Upgrade) + out.Cluster = in.Cluster.DeepCopy() + out.Status = in.Status.DeepCopy() + out.Upgrade = in.Upgrade.DeepCopy() } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIResponses. @@ -588,7 +588,7 @@ func (in *PGAdminConfiguration) DeepCopyInto(out *PGAdminConfiguration) { *out = new(corev1.SecretKeySelector) (*in).DeepCopyInto(*out) } - in.Settings.DeepCopyInto(&out.Settings) + out.Settings = in.Settings.DeepCopy() } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PGAdminConfiguration. @@ -1550,7 +1550,7 @@ func (in *PGUpgradeStatus) DeepCopy() *PGUpgradeStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PatroniSpec) DeepCopyInto(out *PatroniSpec) { *out = *in - in.DynamicConfiguration.DeepCopyInto(&out.DynamicConfiguration) + out.DynamicConfiguration = in.DynamicConfiguration.DeepCopy() if in.LeaderLeaseDurationSeconds != nil { in, out := &in.LeaderLeaseDurationSeconds, &out.LeaderLeaseDurationSeconds *out = new(int32) @@ -2290,8 +2290,7 @@ func (in *RepoStatus) DeepCopy() *RepoStatus { func (in SchemalessObject) DeepCopyInto(out *SchemalessObject) { { in := &in - clone := in.DeepCopy() - *out = *clone + *out = in.DeepCopy() } } @@ -2386,13 +2385,13 @@ func (in *StandalonePGAdminConfiguration) DeepCopyInto(out *StandalonePGAdminCon *out = new(corev1.SecretKeySelector) (*in).DeepCopyInto(*out) } - in.Gunicorn.DeepCopyInto(&out.Gunicorn) + out.Gunicorn = in.Gunicorn.DeepCopy() if in.LDAPBindPassword != nil { in, out := &in.LDAPBindPassword, &out.LDAPBindPassword *out = new(corev1.SecretKeySelector) (*in).DeepCopyInto(*out) } - in.Settings.DeepCopyInto(&out.Settings) + out.Settings = in.Settings.DeepCopy() } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StandalonePGAdminConfiguration. diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/01--valid-upgrade.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/01--valid-upgrade.yaml deleted file mode 100644 index fa3985231d..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/01--valid-upgrade.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -# This upgrade is valid, but has no pgcluster to work on and should get that condition -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -spec: - # postgres version that is no longer available - fromPostgresVersion: 10 - toPostgresVersion: ${KUTTL_PG_UPGRADE_TO_VERSION} - postgresClusterName: major-upgrade-empty-image diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/01-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/01-assert.yaml deleted file mode 100644 index b7d0f936fb..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/01-assert.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -status: - conditions: - - type: "Progressing" - status: "False" - reason: "PGClusterNotFound" diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/10--cluster.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/10--cluster.yaml deleted file mode 100644 index c85a9b8dae..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/10--cluster.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -# Create the cluster we will do an actual upgrade on, but set the postgres version -# to '10' to force a missing image scenario -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -spec: - # postgres version that is no longer available - postgresVersion: 10 - patroni: - dynamicConfiguration: - postgresql: - parameters: - shared_preload_libraries: pgaudit, set_user, pg_stat_statements, pgnodemx, pg_cron - instances: - - dataVolumeClaimSpec: { accessModes: [ReadWriteOnce], resources: { requests: { storage: 1Gi } } } - backups: - pgbackrest: - repos: - - name: repo1 - volume: - volumeClaimSpec: { accessModes: [ReadWriteOnce], resources: { requests: { storage: 1Gi } } } diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/10-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/10-assert.yaml deleted file mode 100644 index 72e9ff6387..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/10-assert.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -# The cluster is not running due to the missing image, not due to a proper -# shutdown status. -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -status: - conditions: - - type: "Progressing" - status: "False" - reason: "PGClusterNotShutdown" diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/11--shutdown-cluster.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/11--shutdown-cluster.yaml deleted file mode 100644 index 316f3a5472..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/11--shutdown-cluster.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -# Shutdown the cluster -- but without the annotation. -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -spec: - shutdown: true diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/11-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/11-assert.yaml deleted file mode 100644 index 5bd9d447cb..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/11-assert.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -# Since the cluster is missing the annotation, we get this condition -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -status: - conditions: - - type: "Progressing" - status: "False" - reason: "PGClusterPrimaryNotIdentified" diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/12--start-and-update-version.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/12--start-and-update-version.yaml deleted file mode 100644 index fcdf4f62e3..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/12--start-and-update-version.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -# Update the postgres version and restart the cluster. -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -spec: - shutdown: false - postgresVersion: ${KUTTL_PG_UPGRADE_FROM_VERSION} ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -spec: - # update postgres version - fromPostgresVersion: ${KUTTL_PG_UPGRADE_FROM_VERSION} diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/12-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/12-assert.yaml deleted file mode 100644 index 14c33cccfe..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/12-assert.yaml +++ /dev/null @@ -1,31 +0,0 @@ ---- -# Wait for the instances to be ready and the replica backup to complete -# by waiting for the status to signal pods ready and pgbackrest stanza created -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -spec: - postgresVersion: ${KUTTL_PG_UPGRADE_FROM_VERSION} -status: - instances: - - name: '00' - replicas: 1 - readyReplicas: 1 - updatedReplicas: 1 - pgbackrest: - repos: - - name: repo1 - replicaCreateBackupComplete: true - stanzaCreated: true ---- -# Even when the cluster exists, the pgupgrade is not progressing because the cluster is not shutdown -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -status: - conditions: - - type: "Progressing" - status: "False" - reason: "PGClusterNotShutdown" diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/13--shutdown-cluster.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/13--shutdown-cluster.yaml deleted file mode 100644 index 316f3a5472..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/13--shutdown-cluster.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -# Shutdown the cluster -- but without the annotation. -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -spec: - shutdown: true diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/13-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/13-assert.yaml deleted file mode 100644 index 78e51e566a..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/13-assert.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -# Since the cluster is missing the annotation, we get this condition -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -status: - conditions: - - type: "Progressing" - status: "False" - reason: "PGClusterMissingRequiredAnnotation" diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/14--annotate-cluster.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/14--annotate-cluster.yaml deleted file mode 100644 index 2fa2c949a9..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/14--annotate-cluster.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -# Annotate the cluster for an upgrade. -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image - annotations: - postgres-operator.crunchydata.com/allow-upgrade: empty-image-upgrade diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/14-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/14-assert.yaml deleted file mode 100644 index bd828180f4..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/14-assert.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -# Now that the postgres cluster is shut down and annotated, the pgupgrade -# can finish reconciling. We know the reconciliation is complete when -# the pgupgrade status is succeeded and the postgres cluster status -# has the updated version. -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PGUpgrade -metadata: - name: empty-image-upgrade -status: - conditions: - - type: "Progressing" - status: "False" - - type: "Succeeded" - status: "True" ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -status: - postgresVersion: ${KUTTL_PG_UPGRADE_TO_VERSION} diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/15--start-cluster.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/15--start-cluster.yaml deleted file mode 100644 index e5f270fb2f..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/15--start-cluster.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -# Once the pgupgrade is finished, update the version and set shutdown to false -# in the postgres cluster -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -spec: - postgresVersion: ${KUTTL_PG_UPGRADE_TO_VERSION} - shutdown: false diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/15-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/15-assert.yaml deleted file mode 100644 index dfcbd4c819..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/15-assert.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -# Wait for the instances to be ready with the target Postgres version. -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade-empty-image -status: - postgresVersion: ${KUTTL_PG_UPGRADE_TO_VERSION} - instances: - - name: '00' - replicas: 1 - readyReplicas: 1 - updatedReplicas: 1 - pgbackrest: - repos: - - name: repo1 - replicaCreateBackupComplete: true - stanzaCreated: true diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/16-check-pgbackrest.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/16-check-pgbackrest.yaml deleted file mode 100644 index 969e7f0ac3..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/16-check-pgbackrest.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: -# Check that the pgbackrest setup has successfully completed -- script: | - kubectl -n "${NAMESPACE}" exec "statefulset.apps/major-upgrade-empty-image-repo-host" -c pgbackrest -- pgbackrest check --stanza=db diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/17--check-version.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/17--check-version.yaml deleted file mode 100644 index 5315c1d14f..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/17--check-version.yaml +++ /dev/null @@ -1,39 +0,0 @@ ---- -# Check the version reported by PostgreSQL -apiVersion: batch/v1 -kind: Job -metadata: - name: major-upgrade-empty-image-after - labels: { postgres-operator-test: kuttl } -spec: - backoffLimit: 6 - template: - metadata: - labels: { postgres-operator-test: kuttl } - spec: - restartPolicy: Never - containers: - - name: psql - image: ${KUTTL_PSQL_IMAGE} - env: - - name: PGURI - valueFrom: { secretKeyRef: { name: major-upgrade-empty-image-pguser-major-upgrade-empty-image, key: uri } } - - # Do not wait indefinitely. - - { name: PGCONNECT_TIMEOUT, value: '5' } - - # Note: the `$$$$` is reduced to `$$` by Kubernetes. - # - https://kubernetes.io/docs/tasks/inject-data-application/ - command: - - psql - - $(PGURI) - - --quiet - - --echo-errors - - --set=ON_ERROR_STOP=1 - - --command - - | - DO $$$$ - BEGIN - ASSERT current_setting('server_version_num') LIKE '${KUTTL_PG_UPGRADE_TO_VERSION}%', - format('got %L', current_setting('server_version_num')); - END $$$$; diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/17-assert.yaml b/testing/kuttl/e2e-other/major-upgrade-missing-image/17-assert.yaml deleted file mode 100644 index 56289c35c1..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/17-assert.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: major-upgrade-empty-image-after -status: - succeeded: 1 diff --git a/testing/kuttl/e2e-other/major-upgrade-missing-image/README.md b/testing/kuttl/e2e-other/major-upgrade-missing-image/README.md deleted file mode 100644 index 341cc854f7..0000000000 --- a/testing/kuttl/e2e-other/major-upgrade-missing-image/README.md +++ /dev/null @@ -1,36 +0,0 @@ -## Major upgrade missing image tests - -This is a variation derived from our major upgrade KUTTL tests designed to -test scenarios where required container images are not defined in either the -PostgresCluster spec or via the RELATED_IMAGES environment variables. - -### Basic PGUpgrade controller and CRD instance validation - -* 01--valid-upgrade: create a valid PGUpgrade instance -* 01-assert: check that the PGUpgrade instance exists and has the expected status - -### Verify new statuses for missing required container images - -* 10--cluster: create the cluster with an unavailable image (i.e. Postgres 10) -* 10-assert: check that the PGUpgrade instance has the expected reason: "PGClusterNotShutdown" -* 11-shutdown-cluster: set the spec.shutdown value to 'true' as required for upgrade -* 11-assert: check that the new reason is set, "PGClusterPrimaryNotIdentified" - -### Update to an available Postgres version, start and upgrade PostgresCluster - -* 12--start-and-update-version: update the Postgres version on both CRD instances and set 'shutdown' to false -* 12-assert: verify that the cluster is running and the PGUpgrade instance now has the new status info with reason: "PGClusterNotShutdown" -* 13--shutdown-cluster: set spec.shutdown to 'true' -* 13-assert: check that the PGUpgrade instance has the expected reason: "PGClusterMissingRequiredAnnotation" -* 14--annotate-cluster: set the required annotation -* 14-assert: verify that the upgrade succeeded and the new Postgres version shows in the cluster's status -* 15--start-cluster: set the new Postgres version and spec.shutdown to 'false' - -### Verify upgraded PostgresCluster - -* 15-assert: verify that the cluster is running -* 16-check-pgbackrest: check that the pgbackrest setup has successfully completed -* 17--check-version: check the version reported by PostgreSQL -* 17-assert: assert the Job from the previous step succeeded - - diff --git a/testing/kuttl/e2e/major-upgrade-missing-image/01--valid-upgrade.yaml b/testing/kuttl/e2e/major-upgrade-missing-image/01--valid-upgrade.yaml index fa3985231d..741efead41 100644 --- a/testing/kuttl/e2e/major-upgrade-missing-image/01--valid-upgrade.yaml +++ b/testing/kuttl/e2e/major-upgrade-missing-image/01--valid-upgrade.yaml @@ -6,6 +6,6 @@ metadata: name: empty-image-upgrade spec: # postgres version that is no longer available - fromPostgresVersion: 10 + fromPostgresVersion: 11 toPostgresVersion: ${KUTTL_PG_UPGRADE_TO_VERSION} postgresClusterName: major-upgrade-empty-image diff --git a/testing/kuttl/e2e/major-upgrade-missing-image/10--cluster.yaml b/testing/kuttl/e2e/major-upgrade-missing-image/10--cluster.yaml index c85a9b8dae..f5ef8c029e 100644 --- a/testing/kuttl/e2e/major-upgrade-missing-image/10--cluster.yaml +++ b/testing/kuttl/e2e/major-upgrade-missing-image/10--cluster.yaml @@ -7,7 +7,7 @@ metadata: name: major-upgrade-empty-image spec: # postgres version that is no longer available - postgresVersion: 10 + postgresVersion: 11 patroni: dynamicConfiguration: postgresql: diff --git a/testing/kuttl/e2e/major-upgrade-missing-image/README.md b/testing/kuttl/e2e/major-upgrade-missing-image/README.md index 341cc854f7..1053da29ed 100644 --- a/testing/kuttl/e2e/major-upgrade-missing-image/README.md +++ b/testing/kuttl/e2e/major-upgrade-missing-image/README.md @@ -11,7 +11,7 @@ PostgresCluster spec or via the RELATED_IMAGES environment variables. ### Verify new statuses for missing required container images -* 10--cluster: create the cluster with an unavailable image (i.e. Postgres 10) +* 10--cluster: create the cluster with an unavailable image (i.e. Postgres 11) * 10-assert: check that the PGUpgrade instance has the expected reason: "PGClusterNotShutdown" * 11-shutdown-cluster: set the spec.shutdown value to 'true' as required for upgrade * 11-assert: check that the new reason is set, "PGClusterPrimaryNotIdentified" From a794a94f71768cede662ae56dc1ee00a849cd86c Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 14 Apr 2025 14:22:33 +0200 Subject: [PATCH 013/300] K8SPG-571 grant user access to public schema (#1097) * K8SPG-571 grant user access to public schema * add test case * update database condition * fix unit tests * fix names * fix PR comments * add validation and update new schema access * fix PR comments * delete force * add import * fix tests * fix tests * fix vars * update vars * fix test * fix log level --------- Co-authored-by: Viacheslav Sarzhan --- ...ator.crunchydata.com_postgresclusters.yaml | 4 + .../pgv2.percona.com_perconapgclusters.yaml | 13 +- .../pgv2.percona.com_perconapgclusters.yaml | 13 +- ...ator.crunchydata.com_postgresclusters.yaml | 4 + deploy/bundle.yaml | 17 ++- deploy/cr.yaml | 1 + deploy/crd.yaml | 17 ++- deploy/cw-bundle.yaml | 17 ++- ...custom-user-with-public-schema-access.yaml | 12 ++ e2e-tests/tests/users/13-assert.yaml | 49 ++++++++ .../users/14-write-data-to-custom-db.yaml | 23 ++++ e2e-tests/tests/users/15-assert.yaml | 10 ++ .../users/15-read-from-primary-custom-db.yaml | 19 +++ internal/postgres/users.go | 67 ++++++++++- internal/postgres/users_test.go | 2 +- .../controller/pgcluster/controller_test.go | 113 +++++++++++++++++- .../v2/perconapgcluster_types.go | 5 +- .../v1beta1/postgres_types.go | 4 + .../v1beta1/zz_generated.deepcopy.go | 5 + 19 files changed, 378 insertions(+), 17 deletions(-) create mode 100644 e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml create mode 100644 e2e-tests/tests/users/13-assert.yaml create mode 100644 e2e-tests/tests/users/14-write-data-to-custom-db.yaml create mode 100644 e2e-tests/tests/users/15-assert.yaml create mode 100644 e2e-tests/tests/users/15-read-from-primary-custom-db.yaml diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 29d0220dbd..71655ae050 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -20451,6 +20451,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 211bfedcb1..742c488ac0 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -58,8 +58,8 @@ spec: properties: autoCreateUserSchema: description: |- - Whether or not the cluster has schemas automatically created for the user - defined in `spec.users` for all of the databases listed for that user. + Indicates whether schemas are automatically created for the user + specified in `spec.users` across all databases associated with that user. type: boolean backups: description: PostgreSQL backup configuration @@ -18252,6 +18252,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase @@ -18303,6 +18307,11 @@ spec: - instances - postgresVersion type: object + x-kubernetes-validations: + - message: PostgresVersion must be >= 15 if grantPublicSchemaAccess exists + and is true + rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, + !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: host: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 2d324fbb48..db5017eb69 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -463,8 +463,8 @@ spec: properties: autoCreateUserSchema: description: |- - Whether or not the cluster has schemas automatically created for the user - defined in `spec.users` for all of the databases listed for that user. + Indicates whether schemas are automatically created for the user + specified in `spec.users` across all databases associated with that user. type: boolean backups: description: PostgreSQL backup configuration @@ -18657,6 +18657,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase @@ -18708,6 +18712,11 @@ spec: - instances - postgresVersion type: object + x-kubernetes-validations: + - message: PostgresVersion must be >= 15 if grantPublicSchemaAccess exists + and is true + rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, + !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: host: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 751c1bac73..8c7f4087a2 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -20349,6 +20349,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 9731f4a93c..c022f43ce9 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -760,8 +760,8 @@ spec: properties: autoCreateUserSchema: description: |- - Whether or not the cluster has schemas automatically created for the user - defined in `spec.users` for all of the databases listed for that user. + Indicates whether schemas are automatically created for the user + specified in `spec.users` across all databases associated with that user. type: boolean backups: description: PostgreSQL backup configuration @@ -18954,6 +18954,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase @@ -19005,6 +19009,11 @@ spec: - instances - postgresVersion type: object + x-kubernetes-validations: + - message: PostgresVersion must be >= 15 if grantPublicSchemaAccess exists + and is true + rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, + !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: host: @@ -46837,6 +46846,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase diff --git a/deploy/cr.yaml b/deploy/cr.yaml index cd2b8e3aeb..a9db1ee787 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -72,6 +72,7 @@ spec: # password: # type: ASCII # secretName: "rhino-credentials" +# grantPublicSchemaAccess: false # databaseInitSQL: # key: init.sql diff --git a/deploy/crd.yaml b/deploy/crd.yaml index ea6fbf9b21..c4afacb8be 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -760,8 +760,8 @@ spec: properties: autoCreateUserSchema: description: |- - Whether or not the cluster has schemas automatically created for the user - defined in `spec.users` for all of the databases listed for that user. + Indicates whether schemas are automatically created for the user + specified in `spec.users` across all databases associated with that user. type: boolean backups: description: PostgreSQL backup configuration @@ -18954,6 +18954,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase @@ -19005,6 +19009,11 @@ spec: - instances - postgresVersion type: object + x-kubernetes-validations: + - message: PostgresVersion must be >= 15 if grantPublicSchemaAccess exists + and is true + rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, + !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: host: @@ -46837,6 +46846,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index b10296186e..3846bd5587 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -760,8 +760,8 @@ spec: properties: autoCreateUserSchema: description: |- - Whether or not the cluster has schemas automatically created for the user - defined in `spec.users` for all of the databases listed for that user. + Indicates whether schemas are automatically created for the user + specified in `spec.users` across all databases associated with that user. type: boolean backups: description: PostgreSQL backup configuration @@ -18954,6 +18954,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase @@ -19005,6 +19009,11 @@ spec: - instances - postgresVersion type: object + x-kubernetes-validations: + - message: PostgresVersion must be >= 15 if grantPublicSchemaAccess exists + and is true + rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, + !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: host: @@ -46837,6 +46846,10 @@ spec: type: string type: array x-kubernetes-list-type: set + grantPublicSchemaAccess: + description: Grant the user access to the public schema in each + database listed under `databases`. + type: boolean name: description: |- The name of this PostgreSQL user. The value may contain only lowercase diff --git a/e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml b/e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml new file mode 100644 index 0000000000..99c81c5d0d --- /dev/null +++ b/e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=json -p '[{"op":"add", "path":"/spec/autoCreateUserSchema","value":true},{"op":"add", "path":"/spec/users","value":[{"name":"chico","databases":["spain"],"password":{"type":"ASCII"},"secretName":"chico-credentials", "grantPublicSchemaAccess": true}]}]' + sleep 10 diff --git a/e2e-tests/tests/users/13-assert.yaml b/e2e-tests/tests/users/13-assert.yaml new file mode 100644 index 0000000000..934432d24b --- /dev/null +++ b/e2e-tests/tests/users/13-assert.yaml @@ -0,0 +1,49 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: users + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: users + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: users +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/users/14-write-data-to-custom-db.yaml b/e2e-tests/tests/users/14-write-data-to-custom-db.yaml new file mode 100644 index 0000000000..7c37c66517 --- /dev/null +++ b/e2e-tests/tests/users/14-write-data-to-custom-db.yaml @@ -0,0 +1,23 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + password=$(get_psql_user_pass chico-credentials) + user='chico' + db_name='spain' + schema='public' + hostname=$(get_pgbouncer_host chico-credentials) + + + run_psql \ + 'SET search_path TO public;CREATE TABLE IF NOT EXISTS customApp (id int PRIMARY KEY);' \ + "-h $hostname -U $user -d $db_name" "$password" + run_psql \ + "INSERT INTO $schema.customApp (id) VALUES (100500)" \ + "-h $hostname -U $user -d $db_name" "$password" + diff --git a/e2e-tests/tests/users/15-assert.yaml b/e2e-tests/tests/users/15-assert.yaml new file mode 100644 index 0000000000..a4d1406345 --- /dev/null +++ b/e2e-tests/tests/users/15-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 10-read-from-primary-custom-db +data: + data: ' 100500' \ No newline at end of file diff --git a/e2e-tests/tests/users/15-read-from-primary-custom-db.yaml b/e2e-tests/tests/users/15-read-from-primary-custom-db.yaml new file mode 100644 index 0000000000..04d6b2c43b --- /dev/null +++ b/e2e-tests/tests/users/15-read-from-primary-custom-db.yaml @@ -0,0 +1,19 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + password=$(get_psql_user_pass chico-credentials) + user='chico' + db_name='spain' + schema='public' + hostname=$(get_pgbouncer_host chico-credentials) + + data=$(run_psql "SELECT * from $schema.customApp;" "-h $hostname -U $user -d $db_name" "$password") + + kubectl create configmap -n "${NAMESPACE}" 10-read-from-primary-custom-db --from-literal=data="${data}" diff --git a/internal/postgres/users.go b/internal/postgres/users.go index 2ea0188c9f..71187583e0 100644 --- a/internal/postgres/users.go +++ b/internal/postgres/users.go @@ -166,15 +166,29 @@ SELECT pg_catalog.format('GRANT ALL PRIVILEGES ON DATABASE %I TO %I', autoCreateUserSchemaAnnotationValue, annotationExists := cluster.Annotations[naming.AutoCreateUserSchemaAnnotation] if annotationExists && strings.EqualFold(autoCreateUserSchemaAnnotationValue, "true") { log.V(1).Info("Writing schemas for users.") - err = WriteUsersSchemasInPostgreSQL(ctx, exec, users) + err = writeUsersSchemasInPostgreSQL(ctx, exec, users) + } + } + + for _, user := range users { + + // We skip if the user has no databases + if len(user.Databases) == 0 { + continue + } + if cluster.CompareVersion("2.7.0") >= 0 && user.GrantPublicSchemaAccess != nil && *user.GrantPublicSchemaAccess { + log.Info("Granting access to public schema for user.", "name", string(user.Name)) + if err = grantUserAccessToPublicSchemaInPostgreSQL(ctx, exec, user); err != nil { + return err + } } } return err } -// WriteUsersSchemasInPostgreSQL will create a schema for each user in each database that user has access to -func WriteUsersSchemasInPostgreSQL(ctx context.Context, exec Executor, +// writeUsersSchemasInPostgreSQL will create a schema for each user in each database that user has access to +func writeUsersSchemasInPostgreSQL(ctx context.Context, exec Executor, users []v1beta1.PostgresUserSpec) error { log := logging.FromContext(ctx) @@ -239,3 +253,50 @@ func WriteUsersSchemasInPostgreSQL(ctx context.Context, exec Executor, } return err } + +// grantUserAccessToPublicSchemaInPostgreSQL grant the specified user access to the public schema within the specified database. +func grantUserAccessToPublicSchemaInPostgreSQL(ctx context.Context, exec Executor, + user v1beta1.PostgresUserSpec) error { + + log := logging.FromContext(ctx) + + var sql bytes.Buffer + + // Prevent unexpected dereferences by emptying "search_path". The "pg_catalog" + // schema is still searched, and only temporary objects can be created. + // - https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-SEARCH-PATH + _, _ = sql.WriteString(`SET search_path TO '';`) + + _, _ = sql.WriteString(`SELECT * FROM json_array_elements_text(:'databases');`) + + databases, _ := json.Marshal(user.Databases) + + stdout, stderr, err := exec.ExecInDatabasesFromQuery(ctx, + sql.String(), + strings.Join([]string{ + // Quiet NOTICE messages from IF EXISTS statements. + `SET client_min_messages = WARNING;`, + + // Grant all privileges on the public schema to the user + `GRANT ALL PRIVILEGES ON SCHEMA public TO :"username";`, + + // Grant all privileges on existing tables and sequences in the public schema + `GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO :"username";`, + `GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO :"username";`, + + // Set default privileges for future objects created in the public schema + `ALTER DEFAULT PRIVILEGES FOR ROLE "username" IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO "username";`, + `ALTER DEFAULT PRIVILEGES FOR ROLE "username" IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO "username";`, + }, "\n"), + map[string]string{ + "databases": string(databases), + "username": string(user.Name), + "ON_ERROR_STOP": "on", // Abort when any one statement fails. + "QUIET": "on", // Do not print successful commands to stdout. + }, + ) + + log.V(1).Info("grant access to public PostgreSQL schemas", "stdout", stdout, "stderr", stderr) + + return err +} diff --git a/internal/postgres/users_test.go b/internal/postgres/users_test.go index 9b9530835e..f132c6f8c1 100644 --- a/internal/postgres/users_test.go +++ b/internal/postgres/users_test.go @@ -209,7 +209,7 @@ func TestWriteUsersSchemasInPostgreSQL(t *testing.T) { return nil } - assert.NilError(t, WriteUsersSchemasInPostgreSQL(ctx, exec, + assert.NilError(t, writeUsersSchemasInPostgreSQL(ctx, exec, []v1beta1.PostgresUserSpec{ { Name: "user-single-db", diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 15f507822f..8909485abe 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -843,7 +843,7 @@ var _ = Describe("Users", Ordered, func() { Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) }) - It("should create defaul and monitor user", func() { + It("should create default and monitor user", func() { _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) Expect(err).NotTo(HaveOccurred()) _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) @@ -1622,3 +1622,114 @@ var _ = Describe("Validate TLS", Ordered, func() { checkSecretProjectionWithCA(cr, cr.Spec.Secrets.CustomReplicationClientTLSSecret, secretName) }) }) + +var _ = Describe("CR Validations", Ordered, func() { + ctx := context.Background() + const crName = "cr-validation" + const ns = crName + t := true + f := false + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName, + Namespace: ns, + }, + } + + BeforeAll(func() { + By("Creating the Namespace to perform the tests") + err := k8sClient.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the Namespace to clean up after the tests") + _ = k8sClient.Delete(ctx, namespace) + }) + + Context("PostgresVersion and grantPublicSchemaAccess validations", Ordered, func() { + When("creating a CR with valid configurations", func() { + It("should accept version >=15 with public schema access", func() { + cr, err := readDefaultCR("cr-validation-1", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.PostgresVersion = 15 + cr.Spec.Users = []v1beta1.PostgresUserSpec{{ + Name: "test", + GrantPublicSchemaAccess: &t, + }} + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + + It("should accept version <15 without public schema access", func() { + cr, err := readDefaultCR("cr-validation-2", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.PostgresVersion = 14 + cr.Spec.Users = []v1beta1.PostgresUserSpec{{ + Name: "test", + GrantPublicSchemaAccess: &f, + }} + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + + It("should accept version <15 with omitted public schema access", func() { + cr, err := readDefaultCR("cr-validation-3", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.PostgresVersion = 14 + cr.Spec.Users = []v1beta1.PostgresUserSpec{{Name: "test"}} + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + + It("should accept when no users are specified", func() { + cr, err := readDefaultCR("cr-validation-4", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.PostgresVersion = 14 + cr.Spec.Users = nil // No users provided + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + }) + + When("creating a CR with invalid configurations", func() { + It("should reject version <15 with public schema access", func() { + cr, err := readDefaultCR("cr-validation-5", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.PostgresVersion = 14 + cr.Spec.Users = []v1beta1.PostgresUserSpec{{ + Name: "test", + GrantPublicSchemaAccess: &t, + }} + + err = k8sClient.Create(ctx, cr) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring( + "PostgresVersion must be >= 15 if grantPublicSchemaAccess exists and is true", + )) + }) + + It("should reject mixed access in multiple users", func() { + cr, err := readDefaultCR("cr-validation-6", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.PostgresVersion = 14 + cr.Spec.Users = []v1beta1.PostgresUserSpec{ + {Name: "test1", GrantPublicSchemaAccess: &f}, + {Name: "test2", GrantPublicSchemaAccess: &t}, + } + + err = k8sClient.Create(ctx, cr) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring( + "PostgresVersion must be >= 15 if grantPublicSchemaAccess exists and is true", + )) + }) + }) + }) +}) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index f22f7422e8..96ca5b68af 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -42,6 +42,7 @@ type PerconaPGCluster struct { Status PerconaPGClusterStatus `json:"status,omitempty"` } +// +kubebuilder:validation:XValidation:rule="!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)",message="PostgresVersion must be >= 15 if grantPublicSchemaAccess exists and is true" type PerconaPGClusterSpec struct { // +optional Metadata *crunchyv1beta1.Metadata `json:"metadata,omitempty"` @@ -167,8 +168,8 @@ type PerconaPGClusterSpec struct { // +optional Extensions ExtensionsSpec `json:"extensions,omitempty"` - // Whether or not the cluster has schemas automatically created for the user - // defined in `spec.users` for all of the databases listed for that user. + // Indicates whether schemas are automatically created for the user + // specified in `spec.users` across all databases associated with that user. // +optional AutoCreateUserSchema *bool `json:"autoCreateUserSchema,omitempty"` } diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgres_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgres_types.go index 562cb1f0f3..30cf44fd17 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgres_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgres_types.go @@ -61,4 +61,8 @@ type PostgresUserSpec struct { // The secret name to generate user, password, connection info this PostgreSQL user. // +optional SecretName PostgresIdentifier `json:"secretName,omitempty"` + + // Grant the user access to the public schema in each database listed under `databases`. + // +optional + GrantPublicSchemaAccess *bool `json:"grantPublicSchemaAccess,omitempty"` } diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index b741dcf28e..5e3b4b8671 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -2167,6 +2167,11 @@ func (in *PostgresUserSpec) DeepCopyInto(out *PostgresUserSpec) { *out = new(PostgresPasswordSpec) **out = **in } + if in.GrantPublicSchemaAccess != nil { + in, out := &in.GrantPublicSchemaAccess, &out.GrantPublicSchemaAccess + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgresUserSpec. From 39ad34902f059305082d1f919e86bc7b9d250a0c Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 14 Apr 2025 15:25:25 +0300 Subject: [PATCH 014/300] K8SPG-732 pgbackrest debug logs streamed to stderr/stdout and logged (#1126) * K8SPG-732 pgbackrest debug logs streamed to stderr/stdout * defer writer errors and move them to the right place --------- Co-authored-by: Viacheslav Sarzhan --- cmd/pgbackrest/main.go | 79 ++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/cmd/pgbackrest/main.go b/cmd/pgbackrest/main.go index 6d12229e0e..0a0c6c71ef 100644 --- a/cmd/pgbackrest/main.go +++ b/cmd/pgbackrest/main.go @@ -16,7 +16,6 @@ package main */ import ( - "bytes" "context" "io" "os" @@ -96,18 +95,13 @@ func main() { cmd := createPGBackRestCommand(cfg) log.Infof("command to execute is [%s]", strings.Join(cmd, " ")) - var output, stderr string // now run the proper exec command depending on whether or not the config hashes should first // be compared prior to executing the PGBackRest command if !cfg.compareHash { - output, stderr, err = runCommand(ctx, k, cfg, cmd) + err = runCommand(ctx, k, cfg, cmd) } else { - output, stderr, err = compareHashAndRunCommand(ctx, k, cfg, cmd) + err = compareHashAndRunCommand(ctx, k, cfg, cmd) } - - // log any output and check for errors - log.Info("output=[" + output + "]") - log.Info("stderr=[" + stderr + "]") if err != nil { log.Fatal(err) } @@ -117,13 +111,11 @@ func main() { // Exec returns the stdout and stderr from running a command inside an existing // container. -func (k *KubeAPI) Exec(ctx context.Context, namespace, pod, container string, stdin io.Reader, command []string) (string, string, error) { - var stdout, stderr bytes.Buffer - +func (k *KubeAPI) Exec(ctx context.Context, namespace, pod, container string, stdin io.Reader, command []string) error { Scheme := runtime.NewScheme() if err := corev1.AddToScheme(Scheme); err != nil { log.Error(err) - return "", "", err + return err } ParameterCodec := runtime.NewParameterCodec(Scheme) @@ -140,15 +132,58 @@ func (k *KubeAPI) Exec(ctx context.Context, namespace, pod, container string, st exec, err := remotecommand.NewSPDYExecutor(k.Config, "POST", request.URL()) - if err == nil { - err = exec.StreamWithContext(ctx, remotecommand.StreamOptions{ - Stdin: stdin, - Stdout: &stdout, - Stderr: &stderr, - }) - } + stdoutReader, stdoutWriter := io.Pipe() + defer func() { + if err := stdoutWriter.Close(); err != nil { + log.Errorf("error closing stdoutWriter: %v", err) + } + }() + + stderrReader, stderrWriter := io.Pipe() + defer func() { + if err := stderrWriter.Close(); err != nil { + log.Errorf("error closing stderrWriter: %v", err) + } + }() + + go streamUsingPrefix("[pgbackrest:stdout]", stdoutReader) + go streamUsingPrefix("[pgbackrest:stderr]", stderrReader) + + err = exec.StreamWithContext(ctx, remotecommand.StreamOptions{ + Stdin: stdin, + Stdout: stdoutWriter, + Stderr: stderrWriter, + }) - return stdout.String(), stderr.String(), err + return err +} + +// streamUsingPrefix reads from an io.Reader line by line and logs each line +// prefixing it with a custom label provided as input. +func streamUsingPrefix(prefix string, reader io.Reader) { + buf := make([]byte, 4096) + line := "" + for { + n, err := reader.Read(buf) + if n > 0 { + line += string(buf[:n]) + for strings.Contains(line, "\n") { + idx := strings.Index(line, "\n") + part := line[:idx] + log.Infof("%s %s", prefix, part) + line = line[idx+1:] + } + } + if err != nil { + if err != io.EOF { + log.Errorf("%s error reading: %v", prefix, err) + } + break + } + } + if line != "" { + log.Infof("%s %s", prefix, line) + } } func NewConfig() (*rest.Config, error) { @@ -313,7 +348,7 @@ func createPGBackRestCommand(cfg config) []string { // command. Only if the hashes match will the pgBackRest command be run, otherwise and error will // be written and exit code 1 will be returned. This is done to ensure a pgBackRest command is only // run when it can be verified that the exepected configuration is present. -func compareHashAndRunCommand(ctx context.Context, kubeapi *KubeAPI, cfg config, cmd []string) (string, string, error) { +func compareHashAndRunCommand(ctx context.Context, kubeapi *KubeAPI, cfg config, cmd []string) error { // the base script used in both the local and exec commands created below baseScript := ` shopt -s globstar @@ -352,7 +387,7 @@ fi // runCommand runs the provided pgBackRest command according to the configuration // provided -func runCommand(ctx context.Context, kubeapi *KubeAPI, cfg config, cmd []string) (string, string, error) { +func runCommand(ctx context.Context, kubeapi *KubeAPI, cfg config, cmd []string) error { bashCmd := []string{"bash"} reader := strings.NewReader(strings.Join(cmd, " ")) return kubeapi.Exec(ctx, cfg.namespace, cfg.podName, cfg.container, reader, bashCmd) From ef2afdb91c483698c5a55737621c32ce062966c3 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 14 Apr 2025 15:28:47 +0300 Subject: [PATCH 015/300] K8SPG-708 use perconalab/percona-postgresql-operator:K8SPG-741-3 for init container configuration (#1129) Co-authored-by: Viacheslav Sarzhan --- e2e-tests/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index c60690faca..a5587a1457 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -178,7 +178,7 @@ get_cr() { .spec.users += [{"name":"postgres","password":{"type":"AlphaNumeric"}}] | .spec.users += [{"name":"'${cr_name}'","password":{"type":"AlphaNumeric"}}] | .spec.image = "'$IMAGE_POSTGRESQL'" | - .spec.initContainer.image = "perconalab/percona-postgresql-operator:K8SPG-708-12" | + .spec.initContainer.image = "'$IMAGE'" | .spec.backups.pgbackrest.image = "'$IMAGE_BACKREST'" | .spec.proxy.pgBouncer.image = "'$IMAGE_PGBOUNCER'" | .spec.pmm.image = "'$IMAGE_PMM_CLIENT'" | From 69dbe04d9367f65a977f373482e5a5d7318f8fbf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 16:25:58 +0300 Subject: [PATCH 016/300] CLOUD-727: Bump golangci/golangci-lint-action from 6 to 7 (#1115) * CLOUD-727: Bump golangci/golangci-lint-action from 6 to 7 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6 to 7. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v6...v7) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * set version * fix * use version1 * run migrate command * fixes --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: George Kechagias --- .github/workflows/reviewdog.yml | 2 +- .golangci.yaml | 193 ++++++++++++++++++-------------- 2 files changed, 112 insertions(+), 83 deletions(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 6f9b4b3cf4..797e71d4f2 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -10,7 +10,7 @@ jobs: go-version: '^1.23' - uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v7 with: version: latest only-new-issues: true diff --git a/.golangci.yaml b/.golangci.yaml index 3618ff73b3..1d6c55067b 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,90 +1,119 @@ -# https://golangci-lint.run/usage/configuration/ - +version: "2" +run: + build-tags: + - envtest linters: - disable: - - contextcheck - - gci - - gofumpt - - goimports enable: + - asasalint + - asciicheck + - bidichk + - bodyclose - depguard + - durationcheck + - errchkjson + - errorlint + - exhaustive + - gocheckcompilerdirectives + - gochecksumtype - gomodguard - - gosimple + - gosec + - gosmopolitan - importas + - loggercheck + - makezero - misspell + - musttag + - nilerr + - nilnesserr + - noctx + - protogetter + - reassign + - recvcheck + - rowserrcheck + - spancheck + - sqlclosecheck + - testifylint - unconvert - presets: - - bugs - - format - - unused - -linters-settings: - gci: - sections: - - standard - - default - - prefix(github.com/percona) - - depguard: + - unparam + - zerologlint + disable: + - contextcheck + settings: + depguard: + rules: + everything: + deny: + - pkg: io/ioutil + desc: | + Use the "io" and "os" packages instead. See https://go.dev/doc/go1.16#ioutil + not-tests: + files: + - '!$test' + deny: + - pkg: net/http/httptest + desc: Should be used only in tests. + - pkg: testing/* + desc: The "testing" packages should be used only in tests. + - pkg: github.com/percona/percona-postgresql-operator/internal/testing/* + desc: The "internal/testing" packages should be used only in tests. + tests: + files: + - $test + deny: + - pkg: github.com/pkg/errors + desc: Use the "errors" package unless you are interacting with stack traces. + errchkjson: + check-error-free-encoding: true + exhaustive: + default-signifies-exhaustive: true + gomodguard: + blocked: + modules: + - gopkg.in/yaml.v2: + recommendations: + - sigs.k8s.io/yaml + - gopkg.in/yaml.v3: + recommendations: + - sigs.k8s.io/yaml + - gotest.tools: + recommendations: + - gotest.tools/v3 + - k8s.io/kubernetes: + reason: | + k8s.io/kubernetes is for managing dependencies of the Kubernetes project, i.e. building kubelet and kubeadm. + importas: + alias: + - pkg: k8s.io/api/(\w+)/(v[\w\w]+) + alias: $1$2 + - pkg: k8s.io/apimachinery/pkg/apis/(\w+)/(v[\w\d]+) + alias: $1$2 + no-unaliased: true + exclusions: + presets: + - comments + - common-false-positives + - legacy + - std-error-handling rules: - everything: - deny: - - pkg: io/ioutil - desc: > - Use the "io" and "os" packages instead. - See https://go.dev/doc/go1.16#ioutil - - not-tests: - files: ['!$test'] - deny: - - pkg: net/http/httptest - desc: Should be used only in tests. - - - pkg: testing/* - desc: The "testing" packages should be used only in tests. - - - pkg: github.com/percona/percona-postgresql-operator/internal/testing/* - desc: The "internal/testing" packages should be used only in tests. - - tests: - files: ['$test'] - deny: - - pkg: github.com/pkg/errors - desc: Use the "errors" package unless you are interacting with stack traces. - - errchkjson: - check-error-free-encoding: true - - exhaustive: - default-signifies-exhaustive: true - - gomodguard: - blocked: - modules: - - gopkg.in/yaml.v2: { recommendations: [sigs.k8s.io/yaml] } - - gopkg.in/yaml.v3: { recommendations: [sigs.k8s.io/yaml] } - - gotest.tools: { recommendations: [gotest.tools/v3] } - - k8s.io/kubernetes: - reason: > - k8s.io/kubernetes is for managing dependencies of the Kubernetes - project, i.e. building kubelet and kubeadm. - - importas: - alias: - - pkg: k8s.io/api/(\w+)/(v[\w\w]+) - alias: $1$2 - - pkg: k8s.io/apimachinery/pkg/apis/(\w+)/(v[\w\d]+) - alias: $1$2 - no-unaliased: true - -run: - build-tags: - - envtest -issues: - exclude-generated: strict - exclude-rules: - # These value types have unmarshal methods. - # https://github.com/raeperd/recvcheck/issues/7 - - linters: [recvcheck] - path: internal/pki/pki.go - text: 'methods of "(Certificate|PrivateKey)"' + - linters: + - recvcheck + path: internal/pki/pki.go + text: methods of "(Certificate|PrivateKey)" + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + settings: + gci: + sections: + - standard + - default + - prefix(github.com/percona) + exclusions: + paths: + - third_party$ + - builtin$ + - examples$ From 53693c4c69527a9b0a9d07c0b861be2d63ce2d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Mon, 14 Apr 2025 17:54:02 +0300 Subject: [PATCH 017/300] K8SPG-710: Make spec.backups optional (#1021) * K8SPG-710: Make spec.backups optional * add backup-enable-disable test * fix unit tests * add backups.enabled field * address review comments --------- Co-authored-by: Viacheslav Sarzhan --- ...ator.crunchydata.com_postgresclusters.yaml | 3 - .../pgv2.percona.com_perconapgbackups.yaml | 2 + .../pgv2.percona.com_perconapgclusters.yaml | 4 +- .../pgv2.percona.com_perconapgclusters.yaml | 6 +- ...ator.crunchydata.com_postgresclusters.yaml | 3 - deploy/bundle.yaml | 9 +- deploy/crd.yaml | 9 +- deploy/cw-bundle.yaml | 9 +- e2e-tests/run-minikube.csv | 1 + e2e-tests/run-pr.csv | 1 + e2e-tests/run-release.csv | 1 + .../backup-enable-disable/00-assert.yaml | 24 ++++ .../00-deploy-operator.yaml | 13 ++ .../backup-enable-disable/01-assert.yaml | 88 ++++++++++++ .../01-create-cluster.yaml | 12 ++ .../backup-enable-disable/02-assert.yaml | 127 ++++++++++++++++++ .../02-enable-backups.yaml | 22 +++ .../backup-enable-disable/03-assert.yaml | 88 ++++++++++++ .../03-disable-backups.yaml | 13 ++ .../04-check-backups.yaml | 18 +++ .../99-remove-cluster-gracefully.yaml | 21 +++ internal/config/config.go | 3 +- internal/config/config_test.go | 10 +- percona/controller/pgbackup/controller.go | 18 +++ percona/controller/pgcluster/controller.go | 10 +- .../v2/perconapgbackup_types.go | 1 + .../v2/perconapgcluster_types.go | 40 ++++-- .../v2/perconapgcluster_types_test.go | 33 +++++ .../v2/zz_generated.deepcopy.go | 5 + .../v1beta1/pgbackrest_types.go | 2 +- .../v1beta1/postgrescluster_test.go | 6 +- .../v1beta1/postgrescluster_types.go | 9 +- 32 files changed, 559 insertions(+), 52 deletions(-) create mode 100644 e2e-tests/tests/backup-enable-disable/00-assert.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/01-assert.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/01-create-cluster.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/02-assert.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/02-enable-backups.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/03-assert.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/04-check-backups.yaml create mode 100644 e2e-tests/tests/backup-enable-disable/99-remove-cluster-gracefully.yaml diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 71655ae050..0065906af8 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -5084,8 +5084,6 @@ spec: type: object type: object type: object - required: - - repos type: object snapshots: description: VolumeSnapshot configuration @@ -20503,7 +20501,6 @@ spec: - name x-kubernetes-list-type: map required: - - backups - instances - postgresVersion type: object diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml index 533bce418e..a5f789b146 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml @@ -101,6 +101,8 @@ spec: type: string destination: type: string + error: + type: string image: type: string jobName: diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 742c488ac0..085f348860 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -64,6 +64,8 @@ spec: backups: description: PostgreSQL backup configuration properties: + enabled: + type: boolean pgbackrest: description: pgBackRest archive configuration properties: @@ -5246,8 +5248,6 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean - required: - - pgbackrest type: object crVersion: description: |- diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index db5017eb69..15d7c50c18 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -100,6 +100,8 @@ spec: type: string destination: type: string + error: + type: string image: type: string jobName: @@ -469,6 +471,8 @@ spec: backups: description: PostgreSQL backup configuration properties: + enabled: + type: boolean pgbackrest: description: pgBackRest archive configuration properties: @@ -5651,8 +5655,6 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean - required: - - pgbackrest type: object crVersion: description: |- diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 8c7f4087a2..9bc016aff2 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -5074,8 +5074,6 @@ spec: type: object type: object type: object - required: - - repos type: object snapshots: description: VolumeSnapshot configuration @@ -20401,7 +20399,6 @@ spec: - name x-kubernetes-list-type: map required: - - backups - instances - postgresVersion type: object diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index c022f43ce9..5de838c10f 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -395,6 +395,8 @@ spec: type: string destination: type: string + error: + type: string image: type: string jobName: @@ -766,6 +768,8 @@ spec: backups: description: PostgreSQL backup configuration properties: + enabled: + type: boolean pgbackrest: description: pgBackRest archive configuration properties: @@ -5948,8 +5952,6 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean - required: - - pgbackrest type: object crVersion: description: |- @@ -31571,8 +31573,6 @@ spec: type: object type: object type: object - required: - - repos type: object snapshots: description: VolumeSnapshot configuration @@ -46898,7 +46898,6 @@ spec: - name x-kubernetes-list-type: map required: - - backups - instances - postgresVersion type: object diff --git a/deploy/crd.yaml b/deploy/crd.yaml index c4afacb8be..f9dea001cd 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -395,6 +395,8 @@ spec: type: string destination: type: string + error: + type: string image: type: string jobName: @@ -766,6 +768,8 @@ spec: backups: description: PostgreSQL backup configuration properties: + enabled: + type: boolean pgbackrest: description: pgBackRest archive configuration properties: @@ -5948,8 +5952,6 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean - required: - - pgbackrest type: object crVersion: description: |- @@ -31571,8 +31573,6 @@ spec: type: object type: object type: object - required: - - repos type: object snapshots: description: VolumeSnapshot configuration @@ -46898,7 +46898,6 @@ spec: - name x-kubernetes-list-type: map required: - - backups - instances - postgresVersion type: object diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 3846bd5587..e2257e8541 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -395,6 +395,8 @@ spec: type: string destination: type: string + error: + type: string image: type: string jobName: @@ -766,6 +768,8 @@ spec: backups: description: PostgreSQL backup configuration properties: + enabled: + type: boolean pgbackrest: description: pgBackRest archive configuration properties: @@ -5948,8 +5952,6 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean - required: - - pgbackrest type: object crVersion: description: |- @@ -31571,8 +31573,6 @@ spec: type: object type: object type: object - required: - - repos type: object snapshots: description: VolumeSnapshot configuration @@ -46898,7 +46898,6 @@ spec: - name x-kubernetes-list-type: map required: - - backups - instances - postgresVersion type: object diff --git a/e2e-tests/run-minikube.csv b/e2e-tests/run-minikube.csv index 7cba6076bf..0e95f7f03b 100644 --- a/e2e-tests/run-minikube.csv +++ b/e2e-tests/run-minikube.csv @@ -1,3 +1,4 @@ +backup-enable-disable custom-extensions custom-tls demand-backup diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 8c0ba3867f..e8c8d96f05 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -1,3 +1,4 @@ +backup-enable-disable custom-extensions custom-tls demand-backup diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 0162e3cdcb..55e8d44061 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -1,3 +1,4 @@ +backup-enable-disable custom-extensions custom-tls demand-backup diff --git a/e2e-tests/tests/backup-enable-disable/00-assert.yaml b/e2e-tests/tests/backup-enable-disable/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/backup-enable-disable/00-deploy-operator.yaml b/e2e-tests/tests/backup-enable-disable/00-deploy-operator.yaml new file mode 100644 index 0000000000..5d21c58f9d --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/00-deploy-operator.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client + deploy_s3_secrets diff --git a/e2e-tests/tests/backup-enable-disable/01-assert.yaml b/e2e-tests/tests/backup-enable-disable/01-assert.yaml new file mode 100644 index 0000000000..482572aa2f --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/01-assert.yaml @@ -0,0 +1,88 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: some-name + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: some-name-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: some-name + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: some-name + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: some-name + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +spec: + backups: + pgbackrest: {} +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: some-name +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/backup-enable-disable/01-create-cluster.yaml b/e2e-tests/tests/backup-enable-disable/01-create-cluster.yaml new file mode 100644 index 0000000000..16352f5a55 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/01-create-cluster.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "some-name" ${RANDOM} \ + | yq '.spec.backups.enabled=false' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/backup-enable-disable/02-assert.yaml b/e2e-tests/tests/backup-enable-disable/02-assert.yaml new file mode 100644 index 0000000000..4ee33d0ee0 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/02-assert.yaml @@ -0,0 +1,127 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: some-name + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 2 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: some-name-repo-host + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: some-name + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: some-name-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: some-name + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: some-name + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: some-name + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 2 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: some-name +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/backup-enable-disable/02-enable-backups.yaml b/e2e-tests/tests/backup-enable-disable/02-enable-backups.yaml new file mode 100644 index 0000000000..a398996673 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/02-enable-backups.yaml @@ -0,0 +1,22 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + if kubectl -n ${NAMESPACE} get sts some-name-repo-host; then + echo "backups are not disabled properly" + exit 1 + fi + + if [[ $(kubectl get job --no-headers -l postgres-operator.crunchydata.com/pgbackrest-backup=replica-create | wc -l) > 0 ]]; then + echo "backups are not disabled properly" + exit 1 + fi + + get_cr "some-name" ${RANDOM} \ + | yq 'del(.spec.backups.enabled)' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/backup-enable-disable/03-assert.yaml b/e2e-tests/tests/backup-enable-disable/03-assert.yaml new file mode 100644 index 0000000000..0ac1c43206 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/03-assert.yaml @@ -0,0 +1,88 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: some-name + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 3 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: some-name-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: some-name + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: some-name + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: some-name + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: some-name + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +spec: + backups: + pgbackrest: {} +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 3 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: some-name +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml b/e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml new file mode 100644 index 0000000000..dde080db34 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "some-name" ${RANDOM} \ + | yq '.metadata.annotations."pgv2.percona.com/authorizeBackupRemoval"="true"' \ + | yq '.spec.backups.enabled=false' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/backup-enable-disable/04-check-backups.yaml b/e2e-tests/tests/backup-enable-disable/04-check-backups.yaml new file mode 100644 index 0000000000..8706f29df8 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/04-check-backups.yaml @@ -0,0 +1,18 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + if kubectl -n ${NAMESPACE} get sts some-name-repo-host; then + echo "backups are not disabled properly" + exit 1 + fi + + if [[ $(kubectl get job --no-headers -l postgres-operator.crunchydata.com/pgbackrest-backup=replica-create | wc -l) > 0 ]]; then + echo "backups are not disabled properly" + exit 1 + fi diff --git a/e2e-tests/tests/backup-enable-disable/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/backup-enable-disable/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..9cf4dd4275 --- /dev/null +++ b/e2e-tests/tests/backup-enable-disable/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: some-name +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: some-name +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 diff --git a/internal/config/config.go b/internal/config/config.go index 9b02d0d6ee..783f56c3b0 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -124,7 +124,8 @@ func VerifyImageValues(cluster *v1beta1.PostgresCluster) error { var images []string - if PGBackRestContainerImage(cluster) == "" { + // K8SPG-710: Image check will fail without a backup section in PostgresCluster + if cluster.BackupSpecFound() && PGBackRestContainerImage(cluster) == "" { images = append(images, "crunchy-pgbackrest") } if PGAdminContainerImage(cluster) == "" && diff --git a/internal/config/config_test.go b/internal/config/config_test.go index ab9cf02818..f233ff14d7 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -220,9 +220,10 @@ func TestVerifyImageValues(t *testing.T) { verifyImageCheck(t, "RELATED_IMAGE_POSTGRES_14_GIS_3.3", "crunchy-postgres-gis", cluster) }) - t.Run("crunchy-pgbackrest", func(t *testing.T) { - verifyImageCheck(t, "RELATED_IMAGE_PGBACKREST", "crunchy-pgbackrest", cluster) - }) + // K8SPG-710: Image check will fail without a backup section in PostgresCluster + // t.Run("crunchy-pgbackrest", func(t *testing.T) { + // verifyImageCheck(t, "RELATED_IMAGE_PGBACKREST", "crunchy-pgbackrest", cluster) + // }) t.Run("crunchy-pgbouncer", func(t *testing.T) { cluster.Spec.Proxy = new(v1beta1.PostgresProxySpec) @@ -246,7 +247,8 @@ func TestVerifyImageValues(t *testing.T) { t.Run("multiple images", func(t *testing.T) { err := VerifyImageValues(cluster) assert.ErrorContains(t, err, "crunchy-postgres-gis") - assert.ErrorContains(t, err, "crunchy-pgbackrest") + // K8SPG-710: Image check will fail without a backup section in PostgresCluster + // assert.ErrorContains(t, err, "crunchy-pgbackrest") assert.ErrorContains(t, err, "crunchy-pgbouncer") assert.ErrorContains(t, err, "crunchy-pgadmin4") assert.ErrorContains(t, err, "crunchy-postgres-exporter") diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index a6ecc8b170..203b354ea9 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -99,6 +99,24 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") } + if !pgCluster.Spec.Backups.IsEnabled() { + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + bcp := new(v2.PerconaPGBackup) + if err := r.Client.Get(ctx, client.ObjectKeyFromObject(pgBackup), bcp); err != nil { + return errors.Wrap(err, "get PGBackup") + } + + bcp.Status.State = v2.BackupFailed + bcp.Status.Error = "Backups are not enabled in the PerconaPGCluster configuration" + + return r.Client.Status().Update(ctx, bcp) + }); err != nil { + return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") + } + + return reconcile.Result{}, nil + } + if pgCluster.Spec.Pause != nil && *pgCluster.Spec.Pause { log.Info("Can't start backup. PostgresCluster is paused", "pg-backup", pgBackup.Name, "cluster", pgCluster.Name) return reconcile.Result{RequeueAfter: time.Second * 5}, nil diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index bf9da3dbae..b13360340c 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -867,6 +867,10 @@ func (r *PGClusterReconciler) reconcileExternalWatchers(ctx context.Context, cr } func (r *PGClusterReconciler) startExternalWatchers(ctx context.Context, cr *v2.PerconaPGCluster) error { + if !cr.Spec.Backups.IsEnabled() { + return nil + } + if !*cr.Spec.Backups.TrackLatestRestorableTime { return nil } @@ -890,6 +894,10 @@ func (r *PGClusterReconciler) startExternalWatchers(ctx context.Context, cr *v2. } func (r *PGClusterReconciler) stopExternalWatcher(ctx context.Context, cr *v2.PerconaPGCluster) { + if !cr.Spec.Backups.IsEnabled() { + return + } + log := logging.FromContext(ctx) if *cr.Spec.Backups.TrackLatestRestorableTime { return @@ -915,7 +923,7 @@ func (r *PGClusterReconciler) ensureFinalizers(ctx context.Context, cr *v2.Perco return nil } - if *cr.Spec.Backups.TrackLatestRestorableTime { + if cr.Spec.Backups.TrackLatestRestorableTime != nil && *cr.Spec.Backups.TrackLatestRestorableTime { orig := cr.DeepCopy() cr.Finalizers = slices.DeleteFunc(cr.Finalizers, func(f string) bool { return f == pNaming.FinalizerStopWatchersDeprecated diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go index 179944d7dd..27a1e820f5 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go @@ -73,6 +73,7 @@ const ( type PerconaPGBackupStatus struct { JobName string `json:"jobName,omitempty"` State PGBackupState `json:"state,omitempty"` + Error string `json:"error,omitempty"` CompletedAt *metav1.Time `json:"completed,omitempty"` Destination string `json:"destination,omitempty"` BackupType PGBackupType `json:"backupType,omitempty"` diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 96ca5b68af..55b441acc2 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -154,7 +154,6 @@ type PerconaPGClusterSpec struct { Proxy *PGProxySpec `json:"proxy,omitempty"` // PostgreSQL backup configuration - // +kubebuilder:validation:Required // +operator-sdk:csv:customresourcedefinitions:type=spec Backups Backups `json:"backups"` @@ -208,19 +207,21 @@ func (cr *PerconaPGCluster) Default() { t := true f := false - if cr.Spec.Backups.TrackLatestRestorableTime == nil { - cr.Spec.Backups.TrackLatestRestorableTime = &t - } - if cr.Spec.Backups.PGBackRest.Metadata == nil { - cr.Spec.Backups.PGBackRest.Metadata = new(crunchyv1beta1.Metadata) - } - if cr.Spec.Backups.PGBackRest.Metadata.Labels == nil { - cr.Spec.Backups.PGBackRest.Metadata.Labels = make(map[string]string) - } - cr.Spec.Backups.PGBackRest.Metadata.Labels[LabelOperatorVersion] = cr.Spec.CRVersion + if cr.Spec.Backups.IsEnabled() { + if cr.Spec.Backups.TrackLatestRestorableTime == nil { + cr.Spec.Backups.TrackLatestRestorableTime = &t + } + if cr.Spec.Backups.PGBackRest.Metadata == nil { + cr.Spec.Backups.PGBackRest.Metadata = new(crunchyv1beta1.Metadata) + } + if cr.Spec.Backups.PGBackRest.Metadata.Labels == nil { + cr.Spec.Backups.PGBackRest.Metadata.Labels = make(map[string]string) + } + cr.Spec.Backups.PGBackRest.Metadata.Labels[LabelOperatorVersion] = cr.Spec.CRVersion - if cr.Spec.Backups.PGBackRest.Jobs == nil { - cr.Spec.Backups.PGBackRest.Jobs = new(crunchyv1beta1.BackupJobs) + if cr.Spec.Backups.PGBackRest.Jobs == nil { + cr.Spec.Backups.PGBackRest.Jobs = new(crunchyv1beta1.BackupJobs) + } } if cr.Spec.Extensions.BuiltIn.PGStatMonitor == nil { @@ -314,6 +315,7 @@ func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crun repo.BackupSchedules.Full = nil repo.BackupSchedules.Incremental = nil } + postgresCluster.Spec.DataSource = cr.Spec.DataSource postgresCluster.Spec.DatabaseInitSQL = cr.Spec.DatabaseInitSQL postgresCluster.Spec.Patroni = cr.Spec.Patroni @@ -447,15 +449,25 @@ type PerconaPGClusterStatus struct { } type Backups struct { + Enabled *bool `json:"enabled,omitempty"` + // pgBackRest archive configuration - // +kubebuilder:validation:Required + // +optional PGBackRest PGBackRestArchive `json:"pgbackrest"` // Enable tracking latest restorable time TrackLatestRestorableTime *bool `json:"trackLatestRestorableTime,omitempty"` } +func (b Backups) IsEnabled() bool { + return b.Enabled == nil || *b.Enabled +} + func (b Backups) ToCrunchy(version string) crunchyv1beta1.Backups { + if b.Enabled != nil && !*b.Enabled { + return crunchyv1beta1.Backups{} + } + var sc *crunchyv1beta1.PGBackRestSidecars sc = b.PGBackRest.Containers diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go index 56e8be28c8..d5ef124895 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go @@ -2,9 +2,42 @@ package v2 import ( "testing" + + "gotest.tools/v3/assert" ) func TestPerconaPGCluster_Default(t *testing.T) { // cr.Default() should not panic on PerconaPGCluster with empty fields new(PerconaPGCluster).Default() } + +func TestPerconaPGCluster_BackupsEnabled(t *testing.T) { + trueVal := true + falseVal := false + + tests := map[string]struct { + spec PerconaPGClusterSpec + expected bool + }{ + + "Enabled is nil, should return true because default is true": { + spec: PerconaPGClusterSpec{Backups: Backups{Enabled: nil}}, + expected: true, + }, + "Enabled is true, should return true": { + spec: PerconaPGClusterSpec{Backups: Backups{Enabled: &trueVal}}, + expected: true, + }, + "Enabled is false, should return false": { + spec: PerconaPGClusterSpec{Backups: Backups{Enabled: &falseVal}}, + expected: false, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + actual := tt.spec.Backups.IsEnabled() + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index 01fd717aea..812ae6a162 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -18,6 +18,11 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Backups) DeepCopyInto(out *Backups) { *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } in.PGBackRest.DeepCopyInto(&out.PGBackRest) if in.TrackLatestRestorableTime != nil { in, out := &in.TrackLatestRestorableTime, &out.TrackLatestRestorableTime diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go index 995442b777..ed15395653 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go @@ -115,7 +115,7 @@ type PGBackRestArchive struct { // +kubebuilder:validation:MinItems=1 // +listType=map // +listMapKey=name - Repos []PGBackRestRepo `json:"repos"` + Repos []PGBackRestRepo `json:"repos,omitempty"` // Defines configuration for a pgBackRest dedicated repository host. This section is only // applicable if at least one "volume" (i.e. PVC-based) repository is defined in the "repos" diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go index ce20db0bff..dec503f43c 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go @@ -44,8 +44,7 @@ metadata: creationTimestamp: null spec: backups: - pgbackrest: - repos: null + pgbackrest: {} config: {} extensions: {} instances: null @@ -79,8 +78,7 @@ metadata: creationTimestamp: null spec: backups: - pgbackrest: - repos: null + pgbackrest: {} config: {} extensions: {} instances: diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 202bd07dfc..ed89da05cb 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -7,6 +7,7 @@ package v1beta1 import ( "context" "fmt" + "reflect" gover "github.com/hashicorp/go-version" "github.com/pkg/errors" @@ -28,8 +29,8 @@ type PostgresClusterSpec struct { DataSource *DataSource `json:"dataSource,omitempty"` // PostgreSQL backup configuration - // +kubebuilder:validation:Required - Backups Backups `json:"backups"` + // +optional + Backups Backups `json:"backups,omitempty"` // The secret containing the root CA certificate and key for // secure connections to the PostgreSQL server. It will need to contain the @@ -789,3 +790,7 @@ func (cr *PostgresCluster) IsPatroniVer4() (bool, error) { } return patroniVer.Compare(gover.Must(gover.NewVersion("4.0.0"))) >= 0, nil } + +func (cr *PostgresCluster) BackupSpecFound() bool { + return !reflect.DeepEqual(cr.Spec.Backups, Backups{PGBackRest: PGBackRestArchive{}}) +} From bd5bac1810599f998fe6d11fe5a35f565f021896 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 14 Apr 2025 19:38:54 +0200 Subject: [PATCH 018/300] K8SPG-726 add example to CR (#1127) Co-authored-by: Viacheslav Sarzhan --- deploy/cr.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index a9db1ee787..f58f2174a6 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -222,7 +222,9 @@ spec: # memory: 128Mi # sidecars: # - name: testcontainer -# image: mycontainer1:latest +# image: busybox:latest +# command: ["sleep", "30d"] +# securityContext: {} # - name: testcontainer2 # image: mycontainer1:latest # @@ -359,7 +361,9 @@ spec: # # sidecars: # - name: bouncertestcontainer1 -# image: mycontainer1:latest +# image: busybox:latest +# command: ["sleep", "30d"] +# securityContext: {} # # customTLSSecret: # name: keycloakdb-pgbouncer.tls From f0f13b4a08a6d4c9d26c2b8863c30cb0fb8f9f7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Tue, 15 Apr 2025 17:28:48 +0300 Subject: [PATCH 019/300] K8SPG-615: Add initialDelaySeconds for backups (#1124) --- ...ator.crunchydata.com_postgresclusters.yaml | 7 + .../pgv2.percona.com_perconapgclusters.yaml | 7 + cmd/pgbackrest/main.go | 11 ++ .../pgv2.percona.com_perconapgclusters.yaml | 7 + ...ator.crunchydata.com_postgresclusters.yaml | 7 + deploy/bundle.yaml | 14 ++ deploy/cr.yaml | 1 + deploy/crd.yaml | 14 ++ deploy/cw-bundle.yaml | 14 ++ .../controller/postgrescluster/pgbackrest.go | 9 ++ .../postgrescluster/pgbackrest_test.go | 138 ++++++++++++++++++ .../v1beta1/pgbackrest_types.go | 6 + 12 files changed, 235 insertions(+) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 0065906af8..39e54898c7 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -1956,6 +1956,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 085f348860..3ecad50abb 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -2114,6 +2114,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. diff --git a/cmd/pgbackrest/main.go b/cmd/pgbackrest/main.go index 0a0c6c71ef..bda9fc29bf 100644 --- a/cmd/pgbackrest/main.go +++ b/cmd/pgbackrest/main.go @@ -24,6 +24,7 @@ import ( "strconv" "strings" "syscall" + "time" log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" @@ -78,6 +79,16 @@ func main() { } log.Infof("debug flag set to %t", debugFlag) + if delay, found := os.LookupEnv("INITIAL_DELAY_SECS"); found { + delaySecs, err := strconv.ParseInt(delay, 10, 64) + if err != nil { + panic(err) + } + + log.Infof("sleeping for %d seconds", delaySecs) + time.Sleep(time.Duration(delaySecs) * time.Second) + } + config, err := NewConfig() if err != nil { panic(err) diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 15d7c50c18..91112c8f71 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -2521,6 +2521,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 9bc016aff2..06707c0f2f 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -1948,6 +1948,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 5de838c10f..b22290c749 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -2818,6 +2818,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. @@ -28447,6 +28454,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. diff --git a/deploy/cr.yaml b/deploy/cr.yaml index f58f2174a6..5e9781730e 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -514,6 +514,7 @@ spec: repoName: repo1 options: - --type=full +# initialDelaySeconds: 120 repos: - name: repo1 schedules: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index f9dea001cd..73d9b6489d 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -2818,6 +2818,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. @@ -28447,6 +28454,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index e2257e8541..b9226f369a 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -2818,6 +2818,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. @@ -28447,6 +28454,13 @@ spec: description: Defines details for manual pgBackRest backup Jobs properties: + initialDelaySeconds: + description: |- + InitialDelaySeconds defines the number of seconds to wait before starting the backup. + After the backup pod is scheduled, its entrypoint will wait for this number of seconds + before initiating the backup process. + format: int64 + type: integer options: description: |- Command line options to include when running the pgBackRest backup command. diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 89778331ab..1090deee91 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -11,6 +11,7 @@ import ( "reflect" "regexp" "sort" + "strconv" "strings" "time" @@ -860,6 +861,14 @@ func generateBackupJobSpecIntent(ctx context.Context, postgresCluster *v1beta1.P } } + // K8SPG-615 + if m := postgresCluster.Spec.Backups.PGBackRest.Manual; postgresCluster.CompareVersion("2.7.0") >= 0 && m != nil && m.InitialDelaySeconds != 0 { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "INITIAL_DELAY_SECS", + Value: strconv.FormatInt(m.InitialDelaySeconds, 10), + }) + } + if postgresCluster.CompareVersion("2.7.0") >= 0 { if annotations != nil { annotations[naming.DefaultContainerAnnotation] = naming.PGBackRestRepoContainerName diff --git a/internal/controller/postgrescluster/pgbackrest_test.go b/internal/controller/postgrescluster/pgbackrest_test.go index 8d321504eb..170f704dfd 100644 --- a/internal/controller/postgrescluster/pgbackrest_test.go +++ b/internal/controller/postgrescluster/pgbackrest_test.go @@ -2719,6 +2719,144 @@ volumes: } }) }) + + t.Run("InitialDelaySeconds", func(t *testing.T) { + t.Run("<2.7.0", func(t *testing.T) { + cluster := &v1beta1.PostgresCluster{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + naming.LabelVersion: "2.6.0", + }, + }, + Spec: v1beta1.PostgresClusterSpec{ + Backups: v1beta1.Backups{ + PGBackRest: v1beta1.PGBackRestArchive{ + Manual: &v1beta1.PGBackRestManualBackup{ + InitialDelaySeconds: 30, + }, + }, + }, + }, + } + job := generateBackupJobSpecIntent(ctx, + cluster, v1beta1.PGBackRestRepo{}, + "", "", + nil, nil, + ) + + container := job.Template.Spec.Containers[0] + + var envVarFound bool + for _, env := range container.Env { + if env.Name == "INITIAL_DELAY_SECS" { + envVarFound = true + } + } + + assert.Check(t, envVarFound == false) + }) + + t.Run(">=2.7.0", func(t *testing.T) { + cluster := &v1beta1.PostgresCluster{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + naming.LabelVersion: "2.7.0", + }, + }, + Spec: v1beta1.PostgresClusterSpec{ + Backups: v1beta1.Backups{ + PGBackRest: v1beta1.PGBackRestArchive{ + Manual: &v1beta1.PGBackRestManualBackup{ + InitialDelaySeconds: 30, + }, + }, + }, + }, + } + job := generateBackupJobSpecIntent(ctx, + cluster, v1beta1.PGBackRestRepo{}, + "", "", + nil, nil, + ) + + container := job.Template.Spec.Containers[0] + + var envVar corev1.EnvVar + for _, env := range container.Env { + if env.Name == "INITIAL_DELAY_SECS" { + envVar = env + } + } + + if assert.Check(t, envVar.Name == "INITIAL_DELAY_SECS") { + assert.Equal(t, envVar.Value, "30") + } + }) + + t.Run("NoManual", func(t *testing.T) { + cluster := &v1beta1.PostgresCluster{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + naming.LabelVersion: "2.7.0", + }, + }, + Spec: v1beta1.PostgresClusterSpec{ + Backups: v1beta1.Backups{ + PGBackRest: v1beta1.PGBackRestArchive{}, + }, + }, + } + job := generateBackupJobSpecIntent(ctx, + cluster, v1beta1.PGBackRestRepo{}, + "", "", + nil, nil, + ) + + container := job.Template.Spec.Containers[0] + + var envVarFound bool + for _, env := range container.Env { + if env.Name == "INITIAL_DELAY_SECS" { + envVarFound = true + } + } + + assert.Check(t, envVarFound == false) + }) + + t.Run("EmptyValue", func(t *testing.T) { + cluster := &v1beta1.PostgresCluster{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + naming.LabelVersion: "2.7.0", + }, + }, + Spec: v1beta1.PostgresClusterSpec{ + Backups: v1beta1.Backups{ + PGBackRest: v1beta1.PGBackRestArchive{ + Manual: &v1beta1.PGBackRestManualBackup{}, + }, + }, + }, + } + job := generateBackupJobSpecIntent(ctx, + cluster, v1beta1.PGBackRestRepo{}, + "", "", + nil, nil, + ) + + container := job.Template.Spec.Containers[0] + + var envVarFound bool + for _, env := range container.Env { + if env.Name == "INITIAL_DELAY_SECS" { + envVarFound = true + } + } + + assert.Check(t, envVarFound == false) + }) + }) } func TestGenerateRepoHostIntent(t *testing.T) { diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go index ed15395653..e931bc8b11 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go @@ -205,6 +205,12 @@ type PGBackRestManualBackup struct { // https://pgbackrest.org/command.html#command-backup // +optional Options []string `json:"options,omitempty"` + + // InitialDelaySeconds defines the number of seconds to wait before starting the backup. + // After the backup pod is scheduled, its entrypoint will wait for this number of seconds + // before initiating the backup process. + // +optional + InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"` } // PGBackRestRepoHost represents a pgBackRest dedicated repository host From 56c9f76c95ba702403a9902f29ddd0ad5fb7ca45 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Wed, 16 Apr 2025 13:41:12 +0300 Subject: [PATCH 020/300] K8SPG-698: create serviceaccount before statefulset (#1125) * K8SPG-698: create serviceaccount before statefulset https://perconadev.atlassian.net/browse/K8SPG-698 * small fixes * remove update * fix lint --------- Co-authored-by: Viacheslav Sarzhan --- .../controller/postgrescluster/pgbackrest.go | 17 +-- .../controller/pgcluster/controller_test.go | 108 ++++++++++++++++++ 2 files changed, 117 insertions(+), 8 deletions(-) diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 1090deee91..235cea287e 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -1484,6 +1484,15 @@ func (r *Reconciler) reconcilePGBackRest(ctx context.Context, return result, nil } + // reconcile the RBAC required to run pgBackRest Jobs (e.g. for backups) + // K8SPG-698 + sa, err := r.reconcilePGBackRestRBAC(ctx, postgresCluster) + if err != nil { + log.Error(err, "unable to create replica creation backup") + result.Requeue = true + return result, nil + } + var repoHost *appsv1.StatefulSet var repoHostName string // reconcile the pgbackrest repository host @@ -1532,14 +1541,6 @@ func (r *Reconciler) reconcilePGBackRest(ctx context.Context, result.Requeue = true } - // reconcile the RBAC required to run pgBackRest Jobs (e.g. for backups) - sa, err := r.reconcilePGBackRestRBAC(ctx, postgresCluster) - if err != nil { - log.Error(err, "unable to create replica creation backup") - result.Requeue = true - return result, nil - } - // reconcile the pgBackRest stanza for all configuration pgBackRest repos configHashMismatch, err := r.reconcileStanzaCreate(ctx, postgresCluster, instances, configHash) // If a stanza create error then requeue but don't return the error. This prevents diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 8909485abe..74689b22cb 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -1623,6 +1623,114 @@ var _ = Describe("Validate TLS", Ordered, func() { }) }) +type saTestClient struct { + client.Client + + crName string + ns string +} + +func (sc *saTestClient) checkObject(ctx context.Context, obj client.Object) error { + sts, ok := obj.(*appsv1.StatefulSet) + if !ok { + return nil + } + serviceAccountName := sts.Spec.Template.Spec.ServiceAccountName + if serviceAccountName == "" { + return errors.New("it's not expected to have empty service account name") + } + + if err := sc.Get(ctx, types.NamespacedName{ + Name: serviceAccountName, + Namespace: sts.Namespace, + }, new(corev1.ServiceAccount)); err != nil { + if k8serrors.IsNotFound(err) { + return errors.Wrap(err, "test error: service account should be created before the statefulset") + } + return err + } + + return nil +} + +func (sc *saTestClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { + if err := sc.checkObject(ctx, obj); err != nil { + panic(err) // should panic because reconciler can ignore the error + } + return sc.Client.Patch(ctx, obj, patch, opts...) +} + +func (sc *saTestClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + if err := sc.checkObject(ctx, obj); err != nil { + panic(err) // should panic because reconciler can ignore the error + } + return sc.Client.Create(ctx, obj, opts...) +} + +// This test ensures that the ServiceAccount associated with a StatefulSet is created +// before the StatefulSet itself. (K8SPG-698) +// The saTestClient verifies the existence of the ServiceAccount during create, patch, +// or update operations on the StatefulSet. +var _ = Describe("ServiceAccount early creation", Ordered, func() { + ctx := context.Background() + + const crName = "sa-timestamp" + const ns = crName + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName, + Namespace: ns, + }, + } + crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} + + cr, err := readDefaultCR(crName, ns) + It("should read default cr.yaml", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + cr.Default() + reconciler := reconciler(cr) + crunchyReconciler := crunchyReconciler() + + var cl client.Client + + BeforeAll(func() { + cl = &saTestClient{ + Client: k8sClient, + + crName: crName, + ns: ns, + } + reconciler.Client = cl + crunchyReconciler.Client = cl + + By("Creating the Namespace to perform the tests") + err := cl.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the Namespace to perform the tests") + _ = cl.Delete(ctx, namespace) + }) + + It("should create PerconaPGCluster", func() { + status := cr.Status + Expect(cl.Create(ctx, cr)).Should(Succeed()) + cr.Status = status + Expect(cl.Status().Update(ctx, cr)).Should(Succeed()) + }) + + It("Should reconcile", func() { + _, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler.Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) +}) + var _ = Describe("CR Validations", Ordered, func() { ctx := context.Background() const crName = "cr-validation" From f469a7ed8df0a1104ade14b0177360392dabfbed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 13:42:22 +0300 Subject: [PATCH 021/300] CLOUD-727: Bump go.nhat.io/grpcmock from 0.29.0 to 0.30.0 (#1131) Bumps [go.nhat.io/grpcmock](https://github.com/nhatthm/grpcmock) from 0.29.0 to 0.30.0. - [Release notes](https://github.com/nhatthm/grpcmock/releases) - [Commits](https://github.com/nhatthm/grpcmock/compare/v0.29.0...v0.30.0) --- updated-dependencies: - dependency-name: go.nhat.io/grpcmock dependency-version: 0.30.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 10 +++++----- go.sum | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 41160a9f30..2d2c130af6 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 - go.nhat.io/grpcmock v0.29.0 + go.nhat.io/grpcmock v0.30.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 go.opentelemetry.io/otel v1.35.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 @@ -104,7 +104,7 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/robfig/cron/v3 v3.0.1 github.com/sergi/go-diff v1.3.1 // indirect - github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/afero v1.14.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.10.0 github.com/swaggest/assertjson v1.9.0 // indirect @@ -116,7 +116,7 @@ require ( go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.37.0 // indirect + golang.org/x/net v0.39.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect golang.org/x/sync v0.13.0 // indirect golang.org/x/sys v0.32.0 // indirect @@ -126,8 +126,8 @@ require ( golang.org/x/tools v0.31.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250311190419-81fb87f6b8bf // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.32.1 diff --git a/go.sum b/go.sum index b5ff838d97..b4e99d4af7 100644 --- a/go.sum +++ b/go.sum @@ -198,8 +198,8 @@ github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NF github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= +github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -231,10 +231,10 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= -go.nhat.io/aferomock v0.7.0 h1:jip7tIX2Vt3M54mE9PTYMOrTN/IMZqlcpCMyIr/XFEc= -go.nhat.io/aferomock v0.7.0/go.mod h1:DexRX1DiNRZwfGYrMdC5zjA09Mw95LrfYceLBlPZd5Y= -go.nhat.io/grpcmock v0.29.0 h1:O5jRsQxfIc8pgjOoQo1dl3KHNVDL0Wmy0Xc7JoSApEs= -go.nhat.io/grpcmock v0.29.0/go.mod h1:MZqnsQdm+6sNpvUgBFwMK43aJjvDFCKyTbAr/Pvr7Q8= +go.nhat.io/aferomock v0.8.0 h1:jESv25NuTpA/Wga+AOKqKI1lPKdYiBYvxpIUDJWyfPM= +go.nhat.io/aferomock v0.8.0/go.mod h1:thJD/9Yeo+CcIW45u6rNU8WYc1yIWdqfOSpKcGtjAXw= +go.nhat.io/grpcmock v0.30.0 h1:n6LRUTACW6LMj3+U3XTdLqRSbE/qxWlL1Z6wF/FS6jk= +go.nhat.io/grpcmock v0.30.0/go.mod h1:UivGqlV49ExKl3ceD35f2bH6UBs5zfEcYQMkBHqnIfA= go.nhat.io/matcher/v2 v2.0.0 h1:W+rbHi0hKuZHtOQH4U5g+KwyKyfVioIxrxjoGRcUETE= go.nhat.io/matcher/v2 v2.0.0/go.mod h1:cL5oYp0M9A4L8jEGqjmUfy+k7AXVDddoVt6aYIL1r5g= go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= @@ -299,8 +299,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= @@ -362,8 +362,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250311190419-81fb87f6b8bf h1:dHDlF3CWxQkefK9IJx+O8ldY0gLygvrlYRBNbPqDWuY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250311190419-81fb87f6b8bf/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 h1:TwXJCGVREgQ/cl18iY0Z4wJCTL/GmW+Um2oSwZiZPnc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -373,8 +373,8 @@ google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From d7ee7f417027941d6ea1947523aae6c1eaaeb08b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Apr 2025 19:57:41 +0300 Subject: [PATCH 022/300] CLOUD-727: Bump k8s.io/apiextensions-apiserver from 0.32.1 to 0.32.3 (#1130) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.32.1 to 0.32.3. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.32.1...v0.32.3) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.32.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2d2c130af6..de454cc59d 100644 --- a/go.mod +++ b/go.mod @@ -130,7 +130,7 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.32.1 + k8s.io/apiextensions-apiserver v0.32.3 k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 diff --git a/go.sum b/go.sum index b4e99d4af7..d8c39d77dd 100644 --- a/go.sum +++ b/go.sum @@ -400,8 +400,8 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= -k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw= -k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto= +k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= +k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= From 8102bf5e7d9696c710a939f7bf511b3f8ae69906 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:37:53 +0300 Subject: [PATCH 023/300] CLOUD-727: Bump golang.org/x/tools from 0.31.0 to 0.32.0 (#1132) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.31.0 to 0.32.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.31.0...v0.32.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.32.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index de454cc59d..ef680788f2 100644 --- a/go.mod +++ b/go.mod @@ -123,7 +123,7 @@ require ( golang.org/x/term v0.31.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.31.0 + golang.org/x/tools v0.32.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 // indirect diff --git a/go.sum b/go.sum index d8c39d77dd..a2bd55bc50 100644 --- a/go.sum +++ b/go.sum @@ -347,8 +347,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 56cbc36dcef114f810d2af6b7efdd7a402e3ebed Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Fri, 18 Apr 2025 12:54:20 +0300 Subject: [PATCH 024/300] K8SPG-680: add `ReadyForBackup` condition to the `pg-cluster` (#1133) * K8SPG-680: add `ReadyForBackup` condition to the `pg-cluster` https://perconadev.atlassian.net/browse/K8SPG-680 * add unit-tests * fix lint * fix lint * improve unit-test --------- Co-authored-by: Viacheslav Sarzhan --- .../pgv2.percona.com_perconapgclusters.yaml | 56 ++++++ .../pgv2.percona.com_perconapgclusters.yaml | 56 ++++++ deploy/bundle.yaml | 56 ++++++ deploy/crd.yaml | 56 ++++++ deploy/cw-bundle.yaml | 56 ++++++ go.mod | 2 +- go.sum | 4 +- internal/postgres/users.go | 2 +- percona/controller/pgbackup/controller.go | 175 ++++++++++-------- .../controller/pgbackup/controller_test.go | 161 ++++++++++++++++ percona/controller/pgbackup/testutils_test.go | 79 ++++++++ percona/controller/pgcluster/schedule.go | 7 + percona/controller/pgcluster/status.go | 34 ++++ percona/controller/pgcluster/status_test.go | 120 ++++++++++++ percona/k8s/testutils_test.go | 2 +- percona/naming/conditions.go | 5 + .../v2/perconapgcluster_types.go | 4 + .../v2/zz_generated.deepcopy.go | 8 + 18 files changed, 797 insertions(+), 86 deletions(-) create mode 100644 percona/controller/pgbackup/controller_test.go create mode 100644 percona/controller/pgbackup/testutils_test.go create mode 100644 percona/naming/conditions.go diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 3ecad50abb..3b0dfd5196 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -18321,6 +18321,62 @@ spec: !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array host: type: string installedCustomExtensions: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 91112c8f71..1b97dff6da 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -18728,6 +18728,62 @@ spec: !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array host: type: string installedCustomExtensions: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index b22290c749..64cdb850d0 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -19025,6 +19025,62 @@ spec: !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array host: type: string installedCustomExtensions: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 73d9b6489d..bd5bd24781 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -19025,6 +19025,62 @@ spec: !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array host: type: string installedCustomExtensions: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index b9226f369a..3fbb77be04 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -19025,6 +19025,62 @@ spec: !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' status: properties: + conditions: + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array host: type: string installedCustomExtensions: diff --git a/go.mod b/go.mod index ef680788f2..c99bb2d081 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.37.0 - github.com/pganalyze/pg_query_go/v5 v5.1.0 + github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 diff --git a/go.sum b/go.sum index a2bd55bc50..872fdacf2a 100644 --- a/go.sum +++ b/go.sum @@ -169,8 +169,8 @@ github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/pganalyze/pg_query_go/v5 v5.1.0 h1:MlxQqHZnvA3cbRQYyIrjxEjzo560P6MyTgtlaf3pmXg= -github.com/pganalyze/pg_query_go/v5 v5.1.0/go.mod h1:FsglvxidZsVN+Ltw3Ai6nTgPVcK2BPukH3jCDEqc1Ug= +github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= +github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/internal/postgres/users.go b/internal/postgres/users.go index 71187583e0..c878ba1a1d 100644 --- a/internal/postgres/users.go +++ b/internal/postgres/users.go @@ -10,7 +10,7 @@ import ( "encoding/json" "strings" - pg_query "github.com/pganalyze/pg_query_go/v5" + pg_query "github.com/pganalyze/pg_query_go/v6" "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/logging" diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index 203b354ea9..5b4e6a4f32 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -10,6 +10,8 @@ import ( batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/builder" @@ -78,7 +80,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re pgBackup.Default() - if !pgBackup.DeletionTimestamp.IsZero() { + if !pgBackup.DeletionTimestamp.IsZero() || pgBackup.Status.State == v2.BackupFailed { if _, err := runFinalizers(ctx, r.Client, pgBackup); err != nil { return reconcile.Result{}, errors.Wrap(err, "failed to run finalizers") } @@ -91,12 +93,18 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re } } + pgCluster := new(v2.PerconaPGCluster) + if err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: request.Namespace}, pgCluster); err != nil { + if !k8serrors.IsNotFound(err) { + return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") + } + pgCluster = nil + } + switch pgBackup.Status.State { case v2.BackupNew: - pgCluster := &v2.PerconaPGCluster{} - err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: request.Namespace}, pgCluster) - if err != nil { - return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") + if pgCluster == nil { + return reconcile.Result{}, errors.Errorf("PostgresCluster %s is not found", pgBackup.Spec.PGCluster) } if !pgCluster.Spec.Backups.IsEnabled() { @@ -123,7 +131,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re } // start backup only if backup job doesn't exist - _, err = findBackupJob(ctx, r.Client, pgCluster, pgBackup) + _, err := findBackupJob(ctx, r.Client, pgCluster, pgBackup) if err != nil { if !errors.Is(err, ErrBackupJobNotFound) { return reconcile.Result{}, errors.Wrap(err, "find backup job") @@ -147,12 +155,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{}, errors.Errorf("%s repo not defined", pgBackup.Spec.RepoName) } - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - bcp := new(v2.PerconaPGBackup) - if err := r.Client.Get(ctx, client.ObjectKeyFromObject(pgBackup), bcp); err != nil { - return errors.Wrap(err, "get PGBackup") - } - + if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { bcp.Status.Destination = getDestination(pgCluster, pgBackup) bcp.Status.Image = pgCluster.Spec.Backups.PGBackRest.Image bcp.Status.Repo = repo @@ -170,8 +173,6 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re } bcp.Status.State = v2.BackupStarting - - return r.Client.Status().Update(ctx, bcp) }); err != nil { return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") } @@ -179,10 +180,8 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re log.Info("Backup is starting", "backup", pgBackup.Name, "cluster", pgCluster.Name) return reconcile.Result{}, nil case v2.BackupStarting: - pgCluster := &v2.PerconaPGCluster{} - err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: request.Namespace}, pgCluster) - if err != nil { - return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") + if pgCluster == nil { + return reconcile.Result{}, errors.Errorf("PostgresCluster %s is not found", pgBackup.Spec.PGCluster) } job, err := findBackupJob(ctx, r.Client, pgCluster, pgBackup) @@ -190,6 +189,10 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re if errors.Is(err, ErrBackupJobNotFound) { log.Info("Waiting for backup to start") + if err := failIfClusterIsNotReady(ctx, r.Client, pgCluster, pgBackup); err != nil { + return reconcile.Result{}, errors.Wrap(err, "fail if cluster is not ready for backup") + } + return reconcile.Result{RequeueAfter: time.Second * 5}, nil } return reconcile.Result{}, errors.Wrap(err, "find backup job") @@ -216,16 +219,9 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{}, errors.Wrap(err, "update PGBackup") } - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - bcp := new(v2.PerconaPGBackup) - if err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Name, Namespace: pgBackup.Namespace}, bcp); err != nil { - return errors.Wrap(err, "get PGBackup") - } - + if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { bcp.Status.State = v2.BackupRunning bcp.Status.JobName = job.Name - - return r.Client.Status().Update(ctx, bcp) }); err != nil { return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") } @@ -249,14 +245,6 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{RequeueAfter: time.Second * 5}, nil } - pgCluster := &v2.PerconaPGCluster{} - if err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: request.Namespace}, pgCluster); err != nil { - if !k8serrors.IsNotFound(err) { - return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") - } - pgCluster = nil - } - // We need to perform the same steps as in the delete-backup finalizer once the backup has finished or failed. // After that, the finalizer is no longer needed, that's why the RunFinalizer function is used here. done, err := controller.RunFinalizer(ctx, r.Client, pgBackup, pNaming.FinalizerDeleteBackup, deleteBackupFinalizer(r.Client, pgCluster)) @@ -268,29 +256,17 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{RequeueAfter: time.Second * 5}, nil } - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - bcp := new(v2.PerconaPGBackup) - if err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Name, Namespace: pgBackup.Namespace}, bcp); err != nil { - return errors.Wrap(err, "get PGBackup") - } - + if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { bcp.Status.CompletedAt = job.Status.CompletionTime bcp.Status.State = status - - return r.Client.Status().Update(ctx, bcp) }); err != nil { return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") } return reconcile.Result{}, nil case v2.BackupSucceeded: - pgCluster := &v2.PerconaPGCluster{} - err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: request.Namespace}, pgCluster) - if err != nil { - if k8serrors.IsNotFound(err) { - return reconcile.Result{}, nil - } - return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") + if pgCluster == nil { + return reconcile.Result{}, nil } execCli, err := clientcmd.NewClient() @@ -302,15 +278,8 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re if err == nil { log.Info("Got latest restorable timestamp", "timestamp", latestRestorableTime) - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - bcp := new(v2.PerconaPGBackup) - if err := r.Client.Get(ctx, client.ObjectKeyFromObject(pgBackup), bcp); err != nil { - return errors.Wrap(err, "get PGBackup") - } - + if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { bcp.Status.LatestRestorableTime.Time = latestRestorableTime - - return r.Client.Status().Update(ctx, bcp) }); err != nil { return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") } @@ -353,6 +322,9 @@ func deleteBackupFinalizer(c client.Client, pg *v2.PerconaPGCluster) func(ctx co if client.IgnoreNotFound(err) != nil { return errors.Wrap(err, "get backup job") } + if k8serrors.IsNotFound(err) { + job = nil + } rr, err := finishBackup(ctx, c, pgBackup, job) if err != nil { @@ -478,16 +450,9 @@ func updatePGBackrestInfo(ctx context.Context, c client.Client, pod *corev1.Pod, stanzaName = info.Name if pgBackup.Status.BackupName == "" { - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - bcp := new(v2.PerconaPGBackup) - if err := c.Get(ctx, types.NamespacedName{Name: pgBackup.Name, Namespace: pgBackup.Namespace}, bcp); err != nil { - return errors.Wrap(err, "get PGBackup") - } - + if err := updateStatus(ctx, c, pgBackup, func(bcp *v2.PerconaPGBackup) { bcp.Status.BackupName = backup.Label bcp.Status.BackupType = backup.Type - - return c.Status().Update(ctx, bcp) }); err != nil { return errors.Wrap(err, "update PGBackup status") } @@ -505,7 +470,7 @@ func updatePGBackrestInfo(ctx context.Context, c client.Client, pod *corev1.Pod, } func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBackup, job *batchv1.Job) (*reconcile.Result, error) { - if checkBackupJob(job) == v2.BackupSucceeded { + if job != nil && checkBackupJob(job) == v2.BackupSucceeded { readyPod, err := controller.GetReadyInstancePod(ctx, c, pgBackup.Spec.PGCluster, pgBackup.Namespace) if err != nil { return nil, errors.Wrap(err, "get ready instance pod") @@ -516,7 +481,7 @@ func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBa } } - if job.Labels[naming.LabelPGBackRestBackup] != string(naming.BackupManual) { + if job != nil && job.Labels[naming.LabelPGBackRestBackup] != string(naming.BackupManual) { return nil, nil } @@ -574,21 +539,23 @@ func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBa // Remove PGBackRest labels to prevent the job from being // deleted by the cleanupRepoResources method. - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - j := new(batchv1.Job) - if err := c.Get(ctx, client.ObjectKeyFromObject(job), j); err != nil { - if k8serrors.IsNotFound(err) { - return nil + if job != nil { + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + j := new(batchv1.Job) + if err := c.Get(ctx, client.ObjectKeyFromObject(job), j); err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + return errors.Wrap(err, "get job") + } + for k := range naming.PGBackRestLabels(pgBackup.Spec.PGCluster) { + delete(j.Labels, k) } - return errors.Wrap(err, "get job") - } - for k := range naming.PGBackRestLabels(pgBackup.Spec.PGCluster) { - delete(j.Labels, k) - } - return c.Update(ctx, j) - }); err != nil { - return nil, errors.Wrap(err, "update backup job labels") + return c.Update(ctx, j) + }); err != nil { + return nil, errors.Wrap(err, "update backup job labels") + } } if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { @@ -611,7 +578,7 @@ func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBa return &reconcile.Result{RequeueAfter: time.Second * 5}, nil } - if checkBackupJob(job) != v2.BackupSucceeded { + if job != nil && checkBackupJob(job) != v2.BackupSucceeded { // Remove all crunchy labels to prevent the job from being included in // repoResources.manualBackupJobs used in reconcileManualBackup method. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { @@ -715,3 +682,49 @@ func checkBackupJob(job *batchv1.Job) v2.PGBackupState { return v2.BackupRunning } } + +func failIfClusterIsNotReady(ctx context.Context, cl client.Client, pgCluster *v2.PerconaPGCluster, pgBackup *v2.PerconaPGBackup) error { + log := logging.FromContext(ctx) + + condition := meta.FindStatusCondition(pgCluster.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + if condition == nil || condition.Status == metav1.ConditionTrue || condition.LastTransitionTime.Time.Add(2*time.Minute).After(time.Now()) { + return nil + } + + crunchyCluster := new(v1beta1.PostgresCluster) + if err := cl.Get(ctx, client.ObjectKeyFromObject(pgCluster), crunchyCluster); err != nil { + return errors.Wrap(err, "get PostgresCluster") + } + + // Waiting for the crunchy cluster to receive the annotations added by the startBackup function. + _, ok := crunchyCluster.Annotations[pNaming.ToCrunchyAnnotation(naming.PGBackRestBackup)] + if !ok { + return nil + } + _, ok = crunchyCluster.Annotations[pNaming.ToCrunchyAnnotation(pNaming.AnnotationBackupInProgress)] + if !ok { + return nil + } + + log.Info("Cluster is not ready for backup for too long. Setting it's state to Failed") + + if err := updateStatus(ctx, cl, pgBackup, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupFailed + }); err != nil { + return errors.Wrap(err, "update PGBackup status") + } + return nil +} + +func updateStatus(ctx context.Context, cl client.Client, pgBackup *v2.PerconaPGBackup, updateFunc func(bcp *v2.PerconaPGBackup)) error { + return retry.RetryOnConflict(retry.DefaultBackoff, func() error { + bcp := new(v2.PerconaPGBackup) + if err := cl.Get(ctx, client.ObjectKeyFromObject(pgBackup), bcp); err != nil { + return errors.Wrap(err, "get PGBackup") + } + + updateFunc(bcp) + + return cl.Status().Update(ctx, bcp) + }) +} diff --git a/percona/controller/pgbackup/controller_test.go b/percona/controller/pgbackup/controller_test.go new file mode 100644 index 0000000000..bcb13bf8b1 --- /dev/null +++ b/percona/controller/pgbackup/controller_test.go @@ -0,0 +1,161 @@ +package pgbackup + +import ( + "context" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/percona/percona-postgresql-operator/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +func TestFailIfClusterIsNotReady(t *testing.T) { + ctx := context.Background() + + cr, err := readDefaultCR("ready-for-backup", "ready-for-backup") + if err != nil { + t.Fatal(err) + } + cr.Annotations[pNaming.AnnotationBackupInProgress] = "some-backup" + cr.Annotations[naming.PGBackRestBackup] = "some-backup" + + tests := []struct { + name string + cr *v2.PerconaPGCluster + pgBackup *v2.PerconaPGBackup + expectedState v2.PGBackupState + }{ + { + name: "no condition", + cr: cr.DeepCopy(), + pgBackup: &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "some-backup", + Namespace: cr.Namespace, + }, + Status: v2.PerconaPGBackupStatus{ + State: v2.BackupStarting, + }, + }, + expectedState: v2.BackupStarting, + }, + { + name: "true condition", + cr: func() *v2.PerconaPGCluster { + cr := cr.DeepCopy() + cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{ + Type: pNaming.ConditionClusterIsReadyForBackup, + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Now(), + }) + return cr + }(), + pgBackup: &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "some-backup", + Namespace: cr.Namespace, + }, + Status: v2.PerconaPGBackupStatus{ + State: v2.BackupStarting, + }, + }, + expectedState: v2.BackupStarting, + }, + { + name: "false condition with current time", + cr: func() *v2.PerconaPGCluster { + cr := cr.DeepCopy() + cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{ + Type: pNaming.ConditionClusterIsReadyForBackup, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Now(), + }) + return cr + }(), + pgBackup: &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "some-backup", + Namespace: cr.Namespace, + }, + Status: v2.PerconaPGBackupStatus{ + State: v2.BackupStarting, + }, + }, + expectedState: v2.BackupStarting, + }, + { + name: "false condition with old time", + cr: func() *v2.PerconaPGCluster { + cr := cr.DeepCopy() + cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{ + Type: pNaming.ConditionClusterIsReadyForBackup, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: time.Now().Add(-time.Hour)}, + }) + return cr + }(), + pgBackup: &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "some-backup", + Namespace: cr.Namespace, + }, + Status: v2.PerconaPGBackupStatus{ + State: v2.BackupStarting, + }, + }, + expectedState: v2.BackupFailed, + }, + { + name: "false condition with old time without annotations", + cr: func() *v2.PerconaPGCluster { + cr := cr.DeepCopy() + cr.Annotations = make(map[string]string) + cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{ + Type: pNaming.ConditionClusterIsReadyForBackup, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: time.Now().Add(-time.Hour)}, + }) + return cr + }(), + pgBackup: &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "some-backup", + Namespace: cr.Namespace, + }, + Status: v2.PerconaPGBackupStatus{ + State: v2.BackupStarting, + }, + }, + expectedState: v2.BackupStarting, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cl, err := buildFakeClient(ctx, tt.cr, tt.pgBackup) + if err != nil { + t.Fatal(err) + } + + crunchyCluster := new(v1beta1.PostgresCluster) + if err := cl.Get(ctx, client.ObjectKeyFromObject(tt.cr), crunchyCluster); err != nil { + t.Fatal(err) + } + if err := failIfClusterIsNotReady(ctx, cl, tt.cr, tt.pgBackup); err != nil { + t.Fatal(err) + } + bcp := new(v2.PerconaPGBackup) + if err := cl.Get(ctx, client.ObjectKeyFromObject(tt.pgBackup), bcp); err != nil { + t.Fatal(err) + } + if bcp.Status.State != tt.expectedState { + t.Fatalf("expected state: %s; got: %s", tt.expectedState, bcp.Status.State) + } + }) + } +} diff --git a/percona/controller/pgbackup/testutils_test.go b/percona/controller/pgbackup/testutils_test.go new file mode 100644 index 0000000000..77f9a11a18 --- /dev/null +++ b/percona/controller/pgbackup/testutils_test.go @@ -0,0 +1,79 @@ +package pgbackup + +import ( + "context" + "os" + "path/filepath" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + "github.com/percona/percona-postgresql-operator/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +type fakeClient struct { + client.Client +} + +var _ = client.Client(new(fakeClient)) + +func buildFakeClient(ctx context.Context, cr *v2.PerconaPGCluster, objs ...client.Object) (client.Client, error) { + s := scheme.Scheme + + if err := v1beta1.AddToScheme(s); err != nil { + return nil, err + } + if err := v2.AddToScheme(s); err != nil { + return nil, err + } + + objs = append(objs, cr) + cr.Default() + postgresCluster, err := cr.ToCrunchy(ctx, nil, s) + if err != nil { + return nil, err + } + objs = append(objs, postgresCluster) + + dcs := &corev1.Endpoints{ObjectMeta: naming.PatroniDistributedConfiguration(postgresCluster)} + dcs.Annotations = map[string]string{ + "initialize": "system-identifier", + } + objs = append(objs, dcs) + + cl := new(fakeClient) + cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...).Build() + + return cl, nil +} + +func readDefaultCR(name, namespace string) (*v2.PerconaPGCluster, error) { + data, err := os.ReadFile(filepath.Join("..", "..", "..", "deploy", "cr.yaml")) + if err != nil { + return nil, err + } + + cr := &v2.PerconaPGCluster{} + + if err := yaml.Unmarshal(data, cr); err != nil { + return nil, err + } + + cr.Name = name + if cr.Annotations == nil { + cr.Annotations = make(map[string]string) + } + cr.Spec.InitContainer = &v1beta1.InitContainerSpec{ + Image: "some-image", + } + cr.Annotations[pNaming.AnnotationCustomPatroniVersion] = "4.0.0" + cr.Namespace = namespace + cr.Status.Postgres.Version = cr.Spec.PostgresVersion + return cr, nil +} diff --git a/percona/controller/pgcluster/schedule.go b/percona/controller/pgcluster/schedule.go index 3c8d19997f..4515380cf7 100644 --- a/percona/controller/pgcluster/schedule.go +++ b/percona/controller/pgcluster/schedule.go @@ -6,12 +6,14 @@ import ( "github.com/go-logr/logr" "github.com/pkg/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/percona/naming" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -105,6 +107,11 @@ func (r *PGClusterReconciler) createScheduledBackup(log logr.Logger, backupName, log.Info("Cluster is not ready. Can't start scheduled backup") return nil } + condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + if condition != nil && condition.Status == metav1.ConditionFalse { + log.Info("ReadyForBackup condition is set to false. Can't start scheduled backup") + return nil + } pb := &v2.PerconaPGBackup{ ObjectMeta: metav1.ObjectMeta{ diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index 0dd3893fdb..238155cc2b 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -5,9 +5,13 @@ import ( "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" + "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" + pNaming "github.com/percona/percona-postgresql-operator/percona/naming" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -118,6 +122,8 @@ func (r *PGClusterReconciler) updateStatus(ctx context.Context, cr *v2.PerconaPG cluster.Status.State = r.getState(cr, &cluster.Status, status) + updateConditions(cluster, status) + return r.Client.Status().Update(ctx, cluster) }); err != nil { return errors.Wrap(err, "update PerconaPGCluster status") @@ -125,3 +131,31 @@ func (r *PGClusterReconciler) updateStatus(ctx context.Context, cr *v2.PerconaPG return nil } + +func updateConditions(cr *v2.PerconaPGCluster, status *v1beta1.PostgresClusterStatus) { + setClusterNotReadyCondition := func(status metav1.ConditionStatus, reason string) { + existing := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + if existing == nil || existing.Status != status || existing.Reason != reason { + _ = meta.SetStatusCondition(&cr.Status.Conditions, metav1.Condition{ + Type: pNaming.ConditionClusterIsReadyForBackup, + Status: status, + LastTransitionTime: metav1.Now(), + Reason: reason, + }) + } + } + + repoCondition := meta.FindStatusCondition(status.Conditions, postgrescluster.ConditionRepoHostReady) + if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { + setClusterNotReadyCondition(metav1.ConditionFalse, postgrescluster.ConditionRepoHostReady) + return + } + + backupCondition := meta.FindStatusCondition(status.Conditions, postgrescluster.ConditionReplicaCreate) + if backupCondition == nil || backupCondition.Status != metav1.ConditionTrue { + setClusterNotReadyCondition(metav1.ConditionFalse, postgrescluster.ConditionReplicaCreate) + return + } + + setClusterNotReadyCondition(metav1.ConditionTrue, "AllConditionsAreTrue") +} diff --git a/percona/controller/pgcluster/status_test.go b/percona/controller/pgcluster/status_test.go index b4f56f0f93..7a8c3f88c7 100644 --- a/percona/controller/pgcluster/status_test.go +++ b/percona/controller/pgcluster/status_test.go @@ -11,11 +11,14 @@ import ( . "github.com/onsi/gomega" gs "github.com/onsi/gomega/gstruct" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" + pNaming "github.com/percona/percona-postgresql-operator/percona/naming" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -330,6 +333,123 @@ var _ = Describe("PG Cluster status", Ordered, func() { }) }) }) + + Context("Update PG cluster status.conditions", Ordered, func() { + crName := ns + "-conditions" + crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} + + cr, err := readDefaultCR(crName, ns) + It("should read default cr.yaml and create PerconaPGCluster", func() { + Expect(err).NotTo(HaveOccurred()) + status := cr.Status + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + cr.Status = status + Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) + }) + + It("should reconcile and create Crunchy PostgreCluster", func() { + _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + + When("conditions are not set", func() { + It("should reconcile and update conditions", func() { + _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + It("ReadyForBackup condition should be False", func() { + Eventually(func() bool { + err := k8sClient.Get(ctx, crNamespacedName, cr) + return err == nil + }, time.Second*15, time.Millisecond*250).Should(BeTrue()) + + condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + Expect(condition).Should(Not(BeNil())) + Expect(condition.Status).Should(Equal(metav1.ConditionFalse)) + }) + }) + + When("ConditionRepoHostReady is false", func() { + It("ReadyForBackup condition should be False", func() { + updateCrunchyPGClusterStatus(ctx, crNamespacedName, func(pgc *v1beta1.PostgresCluster) { + _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionFalse, + Reason: "test", + }) + _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }) + }) + _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() bool { + err := k8sClient.Get(ctx, crNamespacedName, cr) + return err == nil + }, time.Second*15, time.Millisecond*250).Should(BeTrue()) + + condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + Expect(condition.Status).Should(Equal(metav1.ConditionFalse)) + }) + }) + + When("ConditionReplicaCreate is false", func() { + It("ReadyForBackup condition should be False", func() { + updateCrunchyPGClusterStatus(ctx, crNamespacedName, func(pgc *v1beta1.PostgresCluster) { + _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }) + _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionFalse, + Reason: "test", + }) + }) + _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() bool { + err := k8sClient.Get(ctx, crNamespacedName, cr) + return err == nil + }, time.Second*15, time.Millisecond*250).Should(BeTrue()) + + condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + Expect(condition.Status).Should(Equal(metav1.ConditionFalse)) + }) + }) + + When("both are true", func() { + It("ReadyForBackup condition should be True", func() { + updateCrunchyPGClusterStatus(ctx, crNamespacedName, func(pgc *v1beta1.PostgresCluster) { + _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }) + _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }) + }) + _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() bool { + err := k8sClient.Get(ctx, crNamespacedName, cr) + return err == nil + }, time.Second*15, time.Millisecond*250).Should(BeTrue()) + + condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + Expect(condition.Status).Should(Equal(metav1.ConditionTrue)) + }) + }) + }) }) func reconcileAndAssertState(ctx context.Context, nn types.NamespacedName, cr *v2.PerconaPGCluster, expectedState v2.AppState) { diff --git a/percona/k8s/testutils_test.go b/percona/k8s/testutils_test.go index ab9f773c69..de3297c5a3 100644 --- a/percona/k8s/testutils_test.go +++ b/percona/k8s/testutils_test.go @@ -30,7 +30,7 @@ func (f *fakeClient) Patch(ctx context.Context, obj client.Object, patch client. if !k8serrors.IsNotFound(err) { return err } - if err := f.Client.Create(ctx, obj); err != nil { + if err := f.Create(ctx, obj); err != nil { return err } return f.Client.Patch(ctx, obj, patch, options...) diff --git a/percona/naming/conditions.go b/percona/naming/conditions.go new file mode 100644 index 0000000000..d8e5405eb0 --- /dev/null +++ b/percona/naming/conditions.go @@ -0,0 +1,5 @@ +package naming + +const ( + ConditionClusterIsReadyForBackup = "ReadyForBackup" +) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 55b441acc2..bcb1d2e163 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -446,6 +446,10 @@ type PerconaPGClusterStatus struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=status InstalledCustomExtensions []string `json:"installedCustomExtensions"` + + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status + Conditions []metav1.Condition `json:"conditions,omitempty"` } type Backups struct { diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index 812ae6a162..8a0f75ebb0 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -11,6 +11,7 @@ package v2 import ( "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" ) @@ -792,6 +793,13 @@ func (in *PerconaPGClusterStatus) DeepCopyInto(out *PerconaPGClusterStatus) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PerconaPGClusterStatus. From 7fa76763a356d6054644c60c89fea5e1bbe32c4b Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Fri, 18 Apr 2025 11:55:19 +0200 Subject: [PATCH 025/300] K8SPG-532 add logs (#1128) * K8SPG-532 add logs * fix error message * fix * fix --------- Co-authored-by: Viacheslav Sarzhan --- internal/controller/postgrescluster/pgbackrest.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 235cea287e..21dbcc84fd 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -1608,7 +1608,7 @@ func (r *Reconciler) reconcilePostgresClusterDataSource(ctx context.Context, rootCA *pki.RootCertificateAuthority, backupsSpecFound bool, ) error { - + log := logging.FromContext(ctx).WithValues("reconcileResource", "clusterDataSource") // grab cluster, namespaces and repo name information from the data source sourceClusterName := dataSource.ClusterName // if the data source name is empty then we're restoring in-place and use the current cluster @@ -1699,6 +1699,10 @@ func (r *Reconciler) reconcilePostgresClusterDataSource(ctx context.Context, client.ObjectKey{Name: sourceClusterName, Namespace: sourceClusterNamespace}, sourceCluster); err != nil { if apierrors.IsNotFound(err) { + log.Error(err, "DataSource refers to a non-existent PostgresCluster", + "name", sourceClusterName, + "namespace", sourceClusterNamespace, + ) r.Recorder.Eventf(cluster, corev1.EventTypeWarning, "InvalidDataSource", "PostgresCluster %q does not exist", sourceClusterName) return nil From 4689dadc921d1acb94bb4885b0e021c1fc7ad632 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Wed, 23 Apr 2025 13:01:03 +0300 Subject: [PATCH 026/300] K8SPG-761: add support for the `PGO_WORKERS` env var (#1135) * K8SPG-761: add support for the `PGO_WORKERS` env var https://perconadev.atlassian.net/browse/K8SPG-761 * fix unit-tests * fix * fix unit-test --- cmd/postgres-operator/main.go | 15 ++--- cmd/postgres-operator/main_test.go | 20 +++--- config/manager/default/manager.yaml | 2 + deploy/bundle.yaml | 2 + deploy/cw-bundle.yaml | 2 + deploy/cw-operator.yaml | 2 + deploy/operator.yaml | 2 + .../controller/pgcluster/controller_test.go | 13 +++- percona/runtime/runtime.go | 61 ++++++------------- 9 files changed, 61 insertions(+), 58 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index ad7ffadb88..44bbd39fc6 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -41,7 +41,6 @@ import ( "github.com/percona/percona-postgresql-operator/percona/controller/pgcluster" "github.com/percona/percona-postgresql-operator/percona/controller/pgrestore" perconaPGUpgrade "github.com/percona/percona-postgresql-operator/percona/controller/pgupgrade" - "github.com/percona/percona-postgresql-operator/percona/k8s" perconaRuntime "github.com/percona/percona-postgresql-operator/percona/runtime" "github.com/percona/percona-postgresql-operator/percona/utils/registry" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" @@ -111,15 +110,13 @@ func main() { // deprecation warnings when using an older version of a resource for backwards compatibility). rest.SetDefaultWarningHandler(rest.NoWarnings{}) - namespaces, err := k8s.GetWatchNamespace() + options, err := initManager(ctx) assertNoError(err) mgr, err := perconaRuntime.CreateRuntimeManager( - namespaces, cfg, - false, - false, features, + options, ) assertNoError(err) @@ -260,8 +257,8 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { //+kubebuilder:rbac:groups="coordination.k8s.io",resources="leases",verbs={get,create,update} -func initManager() (runtime.Options, error) { - log := logging.FromContext(context.Background()) +func initManager(ctx context.Context) (runtime.Options, error) { + log := logging.FromContext(ctx) options := runtime.Options{} options.Cache.SyncPeriod = initialize.Pointer(time.Hour) @@ -279,6 +276,10 @@ func initManager() (runtime.Options, error) { options.LeaderElection = true options.LeaderElectionID = lease options.LeaderElectionNamespace = os.Getenv("PGO_NAMESPACE") + } else { + // K8SPG-761 + options.LeaderElection = true + options.LeaderElectionID = perconaRuntime.ElectionID } // Check PGO_TARGET_NAMESPACE for backwards compatibility with diff --git a/cmd/postgres-operator/main_test.go b/cmd/postgres-operator/main_test.go index f369ce6bd3..9235b7d2c2 100644 --- a/cmd/postgres-operator/main_test.go +++ b/cmd/postgres-operator/main_test.go @@ -5,6 +5,7 @@ package main import ( + "context" "reflect" "testing" "time" @@ -14,8 +15,9 @@ import ( ) func TestInitManager(t *testing.T) { + ctx := context.Background() t.Run("Defaults", func(t *testing.T) { - options, err := initManager() + options, err := initManager(ctx) assert.NilError(t, err) if assert.Check(t, options.Cache.SyncPeriod != nil) { @@ -30,12 +32,14 @@ func TestInitManager(t *testing.T) { }) assert.Assert(t, options.Cache.DefaultNamespaces == nil) - assert.Assert(t, options.LeaderElection == false) + assert.Assert(t, options.LeaderElection == true) { options.Cache.SyncPeriod = nil options.Controller.GroupKindConcurrency = nil options.HealthProbeBindAddress = "" + options.LeaderElection = false + options.LeaderElectionID = "" assert.Assert(t, reflect.ValueOf(options).IsZero(), "expected remaining fields to be unset:\n%+v", options) @@ -48,7 +52,7 @@ func TestInitManager(t *testing.T) { t.Run("Invalid", func(t *testing.T) { t.Setenv("PGO_CONTROLLER_LEASE_NAME", "INVALID_NAME") - options, err := initManager() + options, err := initManager(ctx) assert.ErrorContains(t, err, "PGO_CONTROLLER_LEASE_NAME") assert.ErrorContains(t, err, "invalid") @@ -59,7 +63,7 @@ func TestInitManager(t *testing.T) { t.Run("Valid", func(t *testing.T) { t.Setenv("PGO_CONTROLLER_LEASE_NAME", "valid-name") - options, err := initManager() + options, err := initManager(ctx) assert.NilError(t, err) assert.Assert(t, options.LeaderElection == true) assert.Equal(t, options.LeaderElectionNamespace, "test-namespace") @@ -70,7 +74,7 @@ func TestInitManager(t *testing.T) { t.Run("PGO_TARGET_NAMESPACE", func(t *testing.T) { t.Setenv("PGO_TARGET_NAMESPACE", "some-such") - options, err := initManager() + options, err := initManager(ctx) assert.NilError(t, err) assert.Assert(t, cmp.Len(options.Cache.DefaultNamespaces, 1), "expected only one configured namespace") @@ -81,7 +85,7 @@ func TestInitManager(t *testing.T) { t.Run("PGO_TARGET_NAMESPACES", func(t *testing.T) { t.Setenv("PGO_TARGET_NAMESPACES", "some-such,another-one") - options, err := initManager() + options, err := initManager(ctx) assert.NilError(t, err) assert.Assert(t, cmp.Len(options.Cache.DefaultNamespaces, 2), "expect two configured namespaces") @@ -95,7 +99,7 @@ func TestInitManager(t *testing.T) { for _, v := range []string{"-3", "0", "3.14"} { t.Setenv("PGO_WORKERS", v) - options, err := initManager() + options, err := initManager(ctx) assert.NilError(t, err) assert.DeepEqual(t, options.Controller.GroupKindConcurrency, map[string]int{ @@ -107,7 +111,7 @@ func TestInitManager(t *testing.T) { t.Run("Valid", func(t *testing.T) { t.Setenv("PGO_WORKERS", "19") - options, err := initManager() + options, err := initManager(ctx) assert.NilError(t, err) assert.DeepEqual(t, options.Controller.GroupKindConcurrency, map[string]int{ diff --git a/config/manager/default/manager.yaml b/config/manager/default/manager.yaml index 21e536517e..bc132a43cd 100644 --- a/config/manager/default/manager.yaml +++ b/config/manager/default/manager.yaml @@ -35,6 +35,8 @@ spec: value: INFO - name: DISABLE_TELEMETRY value: "false" + - name: PGO_WORKERS + value: "1" ports: - containerPort: 8080 name: metrics diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 64cdb850d0..0768919028 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -47675,6 +47675,8 @@ spec: value: INFO - name: DISABLE_TELEMETRY value: "false" + - name: PGO_WORKERS + value: "1" image: perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 3fbb77be04..0c16506f0d 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -47673,6 +47673,8 @@ spec: value: INFO - name: DISABLE_TELEMETRY value: "false" + - name: PGO_WORKERS + value: "1" image: perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index b7fc3785ea..90232d8f7d 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -42,6 +42,8 @@ spec: value: INFO - name: DISABLE_TELEMETRY value: "false" + - name: PGO_WORKERS + value: "1" image: perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 37959623a3..24e1f7081e 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -45,6 +45,8 @@ spec: value: INFO - name: DISABLE_TELEMETRY value: "false" + - name: PGO_WORKERS + value: "1" image: perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 74689b22cb..c015406287 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -7,6 +7,7 @@ import ( "context" "crypto/md5" //nolint:gosec "fmt" + "os" "strconv" "sync" "time" @@ -24,8 +25,10 @@ import ( "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + metricsServer "sigs.k8s.io/controller-runtime/pkg/metrics/server" "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" + internalRuntime "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/naming" perconaController "github.com/percona/percona-postgresql-operator/percona/controller" @@ -539,7 +542,15 @@ var _ = Describe("Watching secrets", Ordered, func() { Expect(err).NotTo(HaveOccurred()) Expect(err).To(Not(HaveOccurred())) - mgr, err := runtime.CreateRuntimeManager(namespace.Name, cfg, true, true, gate) + + os.Setenv("PGO_TARGET_NAMESPACE", "") + mgr, err := runtime.CreateRuntimeManager(cfg, gate, internalRuntime.Options{ + LeaderElection: false, + HealthProbeBindAddress: "0", + Metrics: metricsServer.Options{ + BindAddress: "0", + }, + }) Expect(err).To(Succeed()) Expect(v2.AddToScheme(mgr.GetScheme())).To(Succeed()) diff --git a/percona/runtime/runtime.go b/percona/runtime/runtime.go index a6e8efe39d..cc2df3e008 100644 --- a/percona/runtime/runtime.go +++ b/percona/runtime/runtime.go @@ -6,43 +6,34 @@ import ( "time" "k8s.io/client-go/rest" - "k8s.io/client-go/util/flowcontrol" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/manager" - metricsServer "sigs.k8s.io/controller-runtime/pkg/metrics/server" r "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/feature" + "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/percona/k8s" ) // default refresh interval in minutes -var refreshInterval = 60 * time.Minute +const refreshInterval time.Duration = 60 * time.Minute -const electionID string = "08db3feb.percona.com" +const ElectionID string = "08db3feb.percona.com" -// CreateRuntimeManager does the same thing as `internal/controller/runtime.CreateRuntimeManager`, -// excet it configures the manager to watch multiple namespaces. -func CreateRuntimeManager(namespaces string, config *rest.Config, disableMetrics, disableLeaderElection bool, features feature.MutableGate) (manager.Manager, error) { - - var leaderElectionID string - if !disableLeaderElection { - leaderElectionID = electionID - } - - options := manager.Options{ - Cache: cache.Options{ - SyncPeriod: &refreshInterval, - }, - Scheme: r.Scheme, - LeaderElection: !disableLeaderElection, - LeaderElectionID: leaderElectionID, +// CreateRuntimeManager wraps internal/controller/runtime.NewManager and modifies the given options: +// - Fully overwrites the Cache field +// - Sets Cache.SyncPeriod to refreshInterval const +// - Sets Cache.DefaultNamespaces by using k8s.GetWatchNamespace() split by "," +// - Sets BaseContext to include the provided feature gates +func CreateRuntimeManager(config *rest.Config, features feature.MutableGate, options manager.Options) (manager.Manager, error) { + namespaces, err := k8s.GetWatchNamespace() + if err != nil { + return nil, err } - options.BaseContext = func() context.Context { - ctx := context.Background() - return feature.NewContext(ctx, features) + options.Cache = cache.Options{ + SyncPeriod: initialize.Pointer(refreshInterval), } - nn := strings.Split(namespaces, ",") if len(nn) > 0 && nn[0] != "" { namespaces := make(map[string]cache.Config) @@ -52,24 +43,10 @@ func CreateRuntimeManager(namespaces string, config *rest.Config, disableMetrics options.Cache.DefaultNamespaces = namespaces } - if disableMetrics { - options.HealthProbeBindAddress = "0" - options.Metrics = metricsServer.Options{ - BindAddress: "0", - } - } - - // Create a copy of the config to avoid modifying the original - configCopy := rest.CopyConfig(config) - - // Ensure throttling is disabled by setting a fake rate limiter - configCopy.RateLimiter = flowcontrol.NewFakeAlwaysRateLimiter() - - // create controller runtime manager - mgr, err := manager.New(configCopy, options) - if err != nil { - return nil, err + options.BaseContext = func() context.Context { + ctx := context.Background() + return feature.NewContext(ctx, features) } - return mgr, nil + return r.NewManager(config, options) } From b11a8d45e51e8586af2cf3243d6e0e977bf3166c Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 12 May 2025 21:29:43 +0300 Subject: [PATCH 027/300] K8SPG-719 use image.tag and image.repository to configure pmm3 server on e2e tests (#1144) * K8SPG-719 use image.tag and image.repository to configure pmm3 server on e2e tests * env vars for pmm3 * configure pmm3 client properly * bump version --- Jenkinsfile | 2 +- e2e-tests/functions | 4 ++-- e2e-tests/release_versions | 2 ++ e2e-tests/tests/monitoring-pmm3/03-create-cluster.yaml | 2 +- e2e-tests/vars.sh | 2 ++ 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index f47161bb50..e761d9a3ff 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -13,7 +13,7 @@ void createCluster(String CLUSTER_SUFFIX) { gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE gcloud config set project $GCP_PROJECT gcloud container clusters list --filter $CLUSTER_NAME-${CLUSTER_SUFFIX} --zone $region --format='csv[no-heading](name)' | xargs gcloud container clusters delete --zone $region --quiet || true - gcloud container clusters create --zone $region $CLUSTER_NAME-${CLUSTER_SUFFIX} --cluster-version=1.29 --machine-type=n1-standard-4 --preemptible --disk-size 30 --num-nodes=\$NODES_NUM --network=jenkins-vpc --subnetwork=jenkins-${CLUSTER_SUFFIX} --no-enable-autoupgrade --cluster-ipv4-cidr=/21 --labels delete-cluster-after-hours=6 --enable-ip-alias && \ + gcloud container clusters create --zone $region $CLUSTER_NAME-${CLUSTER_SUFFIX} --cluster-version=1.30 --machine-type=n1-standard-4 --preemptible --disk-size 30 --num-nodes=\$NODES_NUM --network=jenkins-vpc --subnetwork=jenkins-${CLUSTER_SUFFIX} --no-enable-autoupgrade --cluster-ipv4-cidr=/21 --labels delete-cluster-after-hours=6 --enable-ip-alias && \ kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user jenkins@"$GCP_PROJECT".iam.gserviceaccount.com || ret_val=\$? if [ \${ret_val} -eq 0 ]; then break; fi ret_num=\$((ret_num + 1)) diff --git a/e2e-tests/functions b/e2e-tests/functions index a5587a1457..cacd8d2afe 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -395,8 +395,8 @@ deploy_pmm3_server() { helm repo add percona https://percona.github.io/percona-helm-charts/ helm install monitoring percona/pmm -n "${NAMESPACE}" \ --set fullnameOverride=monitoring \ - --set imageTag=3-dev-latest \ - --set imageRepo=perconalab/pmm-server \ + --set image.tag=${IMAGE_PMM3_SERVER#*:} \ + --set image.repository=${IMAGE_PMM3_SERVER%:*} \ --set service.type=LoadBalancer \ --set platform="$platform" \ --force diff --git a/e2e-tests/release_versions b/e2e-tests/release_versions index ba9200cebc..1bb96ab1a1 100644 --- a/e2e-tests/release_versions +++ b/e2e-tests/release_versions @@ -30,6 +30,8 @@ IMAGE_UPGRADE=percona/percona-postgresql-operator:2.6.0-upgrade IMAGE_PMM_CLIENT=percona/pmm-client:2.44.0 IMAGE_PMM_SERVER=percona/pmm-server:2.44.0 +IMAGE_PMM3_CLIENT=percona/pmm-client:3.1.0 +IMAGE_PMM3_SERVER=percona/pmm-server:3.1.0 # Supported k8s versions GKE_MIN=1.29 diff --git a/e2e-tests/tests/monitoring-pmm3/03-create-cluster.yaml b/e2e-tests/tests/monitoring-pmm3/03-create-cluster.yaml index b794bd1785..1b090182b9 100644 --- a/e2e-tests/tests/monitoring-pmm3/03-create-cluster.yaml +++ b/e2e-tests/tests/monitoring-pmm3/03-create-cluster.yaml @@ -10,5 +10,5 @@ commands: get_cr \ | yq eval '.spec.pmm.enabled=true' - \ - | yq eval '.spec.pmm.image="perconalab/pmm-client:3-dev-latest"' - \ + | yq eval ".spec.pmm.image=\"${IMAGE_PMM3_CLIENT}\"" - \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index d41ab4467d..47a3dd2cf6 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -23,6 +23,8 @@ export BUCKET=${BUCKET:-"pg-operator-testing"} export PMM_SERVER_VERSION=${PMM_SERVER_VERSION:-"9.9.9"} export IMAGE_PMM_CLIENT=${IMAGE_PMM_CLIENT:-"perconalab/pmm-client:dev-latest"} export IMAGE_PMM_SERVER=${IMAGE_PMM_SERVER:-"perconalab/pmm-server:dev-latest"} +export IMAGE_PMM3_CLIENT=${IMAGE_PMM3_CLIENT:-"perconalab/pmm-client:3-dev-latest"} +export IMAGE_PMM3_SERVER=${IMAGE_PMM3_SERVER:-"perconalab/pmm-server:3-dev-latest"} export PGOV1_TAG=${PGOV1_TAG:-"1.4.0"} export PGOV1_VER=${PGOV1_VER:-"14"} From c57cce3e3607a3748ead18d44b5e266d4e803245 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 11:55:14 +0300 Subject: [PATCH 028/300] CLOUD-727: Bump golang.org/x/crypto from 0.37.0 to 0.38.0 (#1146) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.37.0 to 0.38.0. - [Commits](https://github.com/golang/crypto/compare/v0.37.0...v0.38.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.38.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index c99bb2d081..7c295c646e 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( go.opentelemetry.io/otel/sdk v1.35.0 go.opentelemetry.io/otel/trace v1.35.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.37.0 + golang.org/x/crypto v0.38.0 google.golang.org/grpc v1.71.1 gotest.tools/v3 v3.5.2 k8s.io/api v0.32.3 @@ -118,10 +118,10 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.39.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.32.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 872fdacf2a..ebb9d8a7b3 100644 --- a/go.sum +++ b/go.sum @@ -277,8 +277,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -310,8 +310,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -323,18 +323,18 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 8b9604af0a46bdb424248b434eb5ccf569ddc31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 14 May 2025 12:13:47 +0300 Subject: [PATCH 029/300] K8SPG-772: Fix panic if backup completedAt is nil (#1149) * K8SPG-772: Fix panic if backup completedAt is nil * fix golangci-lint --------- Co-authored-by: Viacheslav Sarzhan --- cmd/postgres-operator/main.go | 7 +- percona/testutils/client.go | 41 +++ percona/watcher/wal.go | 12 +- percona/watcher/wal_test.go | 312 ++++++++++++++++++ .../v2/perconapgbackup_types.go | 11 + 5 files changed, 377 insertions(+), 6 deletions(-) create mode 100644 percona/testutils/client.go create mode 100644 percona/watcher/wal_test.go diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 44bbd39fc6..197a8aabe3 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -194,11 +194,8 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { if err := mgr.GetFieldIndexer().IndexField( context.Background(), &v2.PerconaPGBackup{}, - "spec.pgCluster", - func(rawObj client.Object) []string { - backup := rawObj.(*v2.PerconaPGBackup) - return []string{backup.Spec.PGCluster} - }, + v2.IndexFieldPGCluster, + v2.PGClusterIndexerFunc, ); err != nil { return err } diff --git a/percona/testutils/client.go b/percona/testutils/client.go new file mode 100644 index 0000000000..6288e69e9a --- /dev/null +++ b/percona/testutils/client.go @@ -0,0 +1,41 @@ +package testutils + +import ( + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +func BuildFakeClient(initObjs ...client.Object) client.Client { + scheme := runtime.NewScheme() + + perconaTypes := []runtime.Object{ + new(pgv2.PerconaPGCluster), + new(pgv2.PerconaPGClusterList), + new(pgv2.PerconaPGBackup), + new(pgv2.PerconaPGBackupList), + new(pgv2.PerconaPGRestore), + new(pgv2.PerconaPGRestoreList), + new(pgv2.PerconaPGUpgrade), + new(pgv2.PerconaPGUpgradeList), + } + + crunchyTypes := []runtime.Object{ + new(crunchyv1beta1.PostgresCluster), + new(crunchyv1beta1.PostgresClusterList), + new(crunchyv1beta1.PGUpgrade), + new(crunchyv1beta1.PGUpgradeList), + } + + scheme.AddKnownTypes(pgv2.GroupVersion, perconaTypes...) + scheme.AddKnownTypes(crunchyv1beta1.GroupVersion, crunchyTypes...) + + return fake.NewClientBuilder(). + WithScheme(scheme). + WithObjects(initObjs...). + WithIndex(new(pgv2.PerconaPGBackup), pgv2.IndexFieldPGCluster, pgv2.PGClusterIndexerFunc). + Build() +} diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index f28fdf1e58..cb444ced03 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -131,9 +131,19 @@ func getLatestBackup(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGC runningBackupExists := false for _, backup := range backupList.Items { backup := backup + switch backup.Status.State { case pgv2.BackupSucceeded: - if latest.Status.CompletedAt == nil || backup.Status.CompletedAt.After(latest.Status.CompletedAt.Time) { + var completedAt *metav1.Time + + if backup.Status.CompletedAt != nil { + completedAt = backup.Status.CompletedAt + } + if completedAt == nil { + completedAt = &backup.CreationTimestamp + } + + if latest.Status.CompletedAt == nil || completedAt.After(latest.Status.CompletedAt.Time) { latest = &backup } case pgv2.BackupFailed: diff --git a/percona/watcher/wal_test.go b/percona/watcher/wal_test.go new file mode 100644 index 0000000000..086b29bcaf --- /dev/null +++ b/percona/watcher/wal_test.go @@ -0,0 +1,312 @@ +package watcher + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/percona/percona-postgresql-operator/percona/testutils" + pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" +) + +func mustParseTime(layout string, value string) time.Time { + time, err := time.Parse(layout, value) + if err != nil { + panic(err) + } + return time +} + +func TestGetLatestBackup(t *testing.T) { + tests := []struct { + name string + backups []client.Object + latestBackupName string + expectedErr error + }{ + { + name: "no backups", + backups: []client.Object{}, + latestBackupName: "", + expectedErr: errNoBackups, + }, + { + name: "single backup", + backups: []client.Object{ + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup1", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:23:38Z"), + }, + }, + }, + }, + latestBackupName: "backup1", + expectedErr: nil, + }, + { + name: "multiple backups, same cluster", + backups: []client.Object{ + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup1", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:23:38Z"), + }, + }, + }, + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup2", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:24:12Z"), + }, + }, + }, + }, + latestBackupName: "backup2", + expectedErr: nil, + }, + { + name: "multiple backups, different clusters", + backups: []client.Object{ + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup1", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:23:38Z"), + }, + }, + }, + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup2", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:24:12Z"), + }, + }, + }, + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup-from-different-cluster", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:10:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "different-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:14:12Z"), + }, + }, + }, + }, + latestBackupName: "backup2", + expectedErr: nil, + }, + { + name: "single running backup", + backups: []client.Object{ + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup1", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupRunning, + }, + }, + }, + latestBackupName: "", + expectedErr: errRunningBackup, + }, + { + name: "running backup but a backup is already succeeded", + backups: []client.Object{ + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup1", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:23:38Z"), + }, + }, + }, + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup2", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupRunning, + }, + }, + }, + latestBackupName: "backup1", + expectedErr: nil, + }, + { + name: "K8SPG-772: multiple backups, some has no CompletedAt", + backups: []client.Object{ + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup1", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T21:24:12Z"), + }, + }, + }, + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup2", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T22:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + }, + }, + &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup3", + Namespace: "test-ns", + CreationTimestamp: metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T23:00:57Z"), + }, + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + }, + Status: pgv2.PerconaPGBackupStatus{ + State: pgv2.BackupSucceeded, + CompletedAt: &metav1.Time{ + Time: mustParseTime(time.RFC3339, "2024-02-04T23:24:12Z"), + }, + }, + }, + }, + latestBackupName: "backup3", + expectedErr: nil, + }, + } + + ctx := context.Background() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := testutils.BuildFakeClient(tt.backups...) + + cluster := &pgv2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-ns", + }, + } + + latest, err := getLatestBackup(ctx, client, cluster) + if tt.expectedErr != nil { + require.EqualError(t, err, tt.expectedErr.Error()) + assert.Nil(t, latest) + } else { + require.NoError(t, err) + assert.NotNil(t, latest) + assert.Equal(t, latest.Name, tt.latestBackupName) + } + }) + } +} diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go index 27a1e820f5..5e0fd6d3f1 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go @@ -7,6 +7,7 @@ import ( v "github.com/hashicorp/go-version" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -60,6 +61,16 @@ type PerconaPGBackupSpec struct { Options []string `json:"options,omitempty"` } +const IndexFieldPGCluster = "spec.pgCluster" + +var PGClusterIndexerFunc client.IndexerFunc = func(obj client.Object) []string { + backup, ok := obj.(*PerconaPGBackup) + if !ok { + return nil + } + return []string{backup.Spec.PGCluster} +} + type PGBackupState string const ( From 49a57e91bb98ee5549a247e1daad5c05c972e462 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 23:35:30 +0300 Subject: [PATCH 030/300] CLOUD-727: Bump golang.org/x/tools from 0.32.0 to 0.33.0 (#1145) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.32.0 to 0.33.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.32.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 7c295c646e..45f74f7f5a 100644 --- a/go.mod +++ b/go.mod @@ -116,14 +116,14 @@ require ( go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.39.0 // indirect + golang.org/x/net v0.40.0 // indirect golang.org/x/oauth2 v0.27.0 // indirect golang.org/x/sync v0.14.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/term v0.32.0 // indirect golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.8.0 // indirect - golang.org/x/tools v0.32.0 + golang.org/x/tools v0.33.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 // indirect diff --git a/go.sum b/go.sum index ebb9d8a7b3..6e0a515eb9 100644 --- a/go.sum +++ b/go.sum @@ -299,8 +299,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= @@ -347,8 +347,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From b3e8a0065c36fcd7dd23a4389e441d706ea4edd9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 23:37:13 +0300 Subject: [PATCH 031/300] CLOUD-727: Bump github.com/aws/aws-sdk-go from 1.55.6 to 1.55.7 (#1142) Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.55.6 to 1.55.7. - [Release notes](https://github.com/aws/aws-sdk-go/releases) - [Changelog](https://github.com/aws/aws-sdk-go/blob/main/CHANGELOG_PENDING.md) - [Commits](https://github.com/aws/aws-sdk-go/compare/v1.55.6...v1.55.7) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go dependency-version: 1.55.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 45f74f7f5a..dfe4937ee9 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go v1.55.6 + github.com/aws/aws-sdk-go v1.55.7 github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/bool64/shared v0.1.5 // indirect diff --git a/go.sum b/go.sum index 6e0a515eb9..ca37a33ec8 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk= -github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= +github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= From c564163c2be13639206da4b574870a6bd6339726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 23:39:12 +0300 Subject: [PATCH 032/300] CLOUD-727: Bump google.golang.org/grpc from 1.71.1 to 1.72.1 (#1150) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.71.1 to 1.72.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.72.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.72.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dfe4937ee9..9a6d1d0f0b 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( go.opentelemetry.io/otel/trace v1.35.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.38.0 - google.golang.org/grpc v1.71.1 + google.golang.org/grpc v1.72.1 gotest.tools/v3 v3.5.2 k8s.io/api v0.32.3 k8s.io/apimachinery v0.32.3 diff --git a/go.sum b/go.sum index ca37a33ec8..a59363e00c 100644 --- a/go.sum +++ b/go.sum @@ -369,8 +369,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= -google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= From eca08d2d8511bb6cf968a23d089c8c5cd5556984 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Mon, 26 May 2025 17:13:15 +0300 Subject: [PATCH 033/300] K8SPG-703: add `internal.percona.com/keep-job` finalizer for backups (#1134) * K8SPG-703: add `internal.percona.com/keep-job` finalizer for backups https://perconadev.atlassian.net/browse/K8SPG-703 * fix * fix tests * fix lint * fix * fix unit-tests * fix lint * fix lint * fix lint --------- Co-authored-by: Viacheslav Sarzhan --- .../controller/postgrescluster/pgbackrest.go | 2 + percona/controller/pgbackup/controller.go | 40 ++++++++++++++++--- percona/controller/pgbackup/testutils_test.go | 4 +- percona/controller/pgcluster/backup.go | 17 +++++--- .../controller/pgcluster/controller_test.go | 4 +- .../controller/pgcluster/testutils_test.go | 4 +- percona/k8s/testutils_test.go | 4 +- percona/naming/finalizers.go | 5 +++ 8 files changed, 63 insertions(+), 17 deletions(-) diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 21dbcc84fd..d470daab30 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -2491,6 +2491,8 @@ func (r *Reconciler) reconcileManualBackup(ctx context.Context, }) backupJob.ObjectMeta.Labels = labels backupJob.ObjectMeta.Annotations = annotations + // K8SPG-703 + backupJob.Finalizers = []string{pNaming.FinalizerKeepJob} // K8SPG-613 initImage, err := k8s.InitImage(ctx, r.Client, postgresCluster, &postgresCluster.Spec.Backups.PGBackRest) diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index 5b4e6a4f32..0661635c9d 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -3,6 +3,7 @@ package pgbackup import ( "context" "path" + "slices" "strings" "time" @@ -131,7 +132,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re } // start backup only if backup job doesn't exist - _, err := findBackupJob(ctx, r.Client, pgCluster, pgBackup) + _, err := findBackupJob(ctx, r.Client, pgBackup) if err != nil { if !errors.Is(err, ErrBackupJobNotFound) { return reconcile.Result{}, errors.Wrap(err, "find backup job") @@ -184,7 +185,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{}, errors.Errorf("PostgresCluster %s is not found", pgBackup.Spec.PGCluster) } - job, err := findBackupJob(ctx, r.Client, pgCluster, pgBackup) + job, err := findBackupJob(ctx, r.Client, pgBackup) if err != nil { if errors.Is(err, ErrBackupJobNotFound) { log.Info("Waiting for backup to start") @@ -231,6 +232,15 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re job := &batchv1.Job{} err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Status.JobName, Namespace: pgBackup.Namespace}, job) if err != nil { + // If something has deleted the job even with the finalizer, we should fail the backup. + if k8serrors.IsNotFound(err) { + if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupFailed + }); err != nil { + return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") + } + return reconcile.Result{}, nil + } return reconcile.Result{}, errors.Wrap(err, "get backup job") } @@ -265,6 +275,21 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{}, nil case v2.BackupSucceeded: + job, err := findBackupJob(ctx, r.Client, pgBackup) + if err == nil && slices.Contains(job.Finalizers, pNaming.FinalizerKeepJob) { + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + j := new(batchv1.Job) + if err := r.Client.Get(ctx, client.ObjectKeyFromObject(job), j); err != nil { + return errors.Wrap(err, "get job") + } + j.Finalizers = slices.DeleteFunc(j.Finalizers, func(s string) bool { return s == pNaming.FinalizerKeepJob }) + + return r.Client.Update(ctx, j) + }); err != nil { + return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") + } + } + if pgCluster == nil { return reconcile.Result{}, nil } @@ -636,8 +661,11 @@ func startBackup(ctx context.Context, c client.Client, pb *v2.PerconaPGBackup) e return nil } -func findBackupJob(ctx context.Context, c client.Client, pg *v2.PerconaPGCluster, pb *v2.PerconaPGBackup) (*batchv1.Job, error) { - if jobName := pb.GetAnnotations()[pNaming.AnnotationPGBackrestBackupJobName]; jobName != "" { +func findBackupJob(ctx context.Context, c client.Client, pb *v2.PerconaPGBackup) (*batchv1.Job, error) { + if jobName := pb.GetAnnotations()[pNaming.AnnotationPGBackrestBackupJobName]; jobName != "" || pb.Status.JobName != "" { + if jobName == "" { + jobName = pb.Status.JobName + } job := new(batchv1.Job) err := c.Get(ctx, types.NamespacedName{Name: jobName, Namespace: pb.Namespace}, job) if err != nil { @@ -648,9 +676,9 @@ func findBackupJob(ctx context.Context, c client.Client, pg *v2.PerconaPGCluster jobList := &batchv1.JobList{} err := c.List(ctx, jobList, - client.InNamespace(pg.Namespace), + client.InNamespace(pb.Namespace), client.MatchingLabelsSelector{ - Selector: naming.PGBackRestBackupJobSelector(pg.Name, pb.Spec.RepoName, naming.BackupManual), + Selector: naming.PGBackRestBackupJobSelector(pb.Spec.PGCluster, pb.Spec.RepoName, naming.BackupManual), }) if err != nil { return nil, errors.Wrap(err, "get backup jobs") diff --git a/percona/controller/pgbackup/testutils_test.go b/percona/controller/pgbackup/testutils_test.go index 77f9a11a18..897b557909 100644 --- a/percona/controller/pgbackup/testutils_test.go +++ b/percona/controller/pgbackup/testutils_test.go @@ -48,7 +48,9 @@ func buildFakeClient(ctx context.Context, cr *v2.PerconaPGCluster, objs ...clien objs = append(objs, dcs) cl := new(fakeClient) - cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...).Build() + cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...). + WithIndex(new(v2.PerconaPGBackup), v2.IndexFieldPGCluster, v2.PGClusterIndexerFunc). + Build() return cl, nil } diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 44639f1b1f..5b432283e5 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -5,6 +5,7 @@ import ( "github.com/pkg/errors" batchv1 "k8s.io/api/batch/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" @@ -87,14 +88,18 @@ func (r *PGClusterReconciler) cleanupOutdatedBackups(ctx context.Context, cr *v2 // After the pg-backup is deleted, the job is not deleted immediately. // We need to set the DeletionTimestamp for a job so that `reconcileBackupJob` doesn't create a new pg-backup before the job deletion. job := new(batchv1.Job) - if err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Status.JobName, Namespace: pgBackup.Namespace}, job); err != nil { + err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Status.JobName, Namespace: pgBackup.Namespace}, job) + if client.IgnoreNotFound(err) != nil { return errors.Wrap(err, "get backup job") } - prop := metav1.DeletePropagationForeground - if err := r.Client.Delete(ctx, job, &client.DeleteOptions{ - PropagationPolicy: &prop, - }); err != nil { - return errors.Wrapf(err, "delete job %s/%s", job.Name, job.Namespace) + // The job may be deleted earlier due to ttlSecondsAfterFinished + if !k8serrors.IsNotFound(err) { + prop := metav1.DeletePropagationForeground + if err := r.Client.Delete(ctx, job, &client.DeleteOptions{ + PropagationPolicy: &prop, + }); err != nil { + return errors.Wrapf(err, "delete job %s/%s", job.Name, job.Namespace) + } } if err := r.Client.Delete(ctx, &pgBackup); err != nil { return errors.Wrapf(err, "delete backup %s/%s", pgBackup.Name, pgBackup.Namespace) diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index c015406287..92bfb7a3d8 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -671,7 +671,7 @@ var _ = Describe("Watching secrets", Ordered, func() { }) It("should reconcile 1 time", func() { - Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*15, time.Millisecond*250). + Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*20, time.Millisecond*250). Should(Equal(reconcileCount + 1)) }) @@ -692,7 +692,7 @@ var _ = Describe("Watching secrets", Ordered, func() { }) It("should reconcile 2 times", func() { - Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*15, time.Millisecond*250). + Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*20, time.Millisecond*250). Should(Equal(reconcileCount + 2)) }) }) diff --git a/percona/controller/pgcluster/testutils_test.go b/percona/controller/pgcluster/testutils_test.go index e9d5cedb2d..21b8771a32 100644 --- a/percona/controller/pgcluster/testutils_test.go +++ b/percona/controller/pgcluster/testutils_test.go @@ -207,7 +207,9 @@ func buildFakeClient(ctx context.Context, cr *v2.PerconaPGCluster, objs ...clien objs = append(objs, dcs) cl := new(fakeClient) - cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...).Build() + cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...). + WithIndex(new(v2.PerconaPGBackup), v2.IndexFieldPGCluster, v2.PGClusterIndexerFunc). + Build() return cl, nil } diff --git a/percona/k8s/testutils_test.go b/percona/k8s/testutils_test.go index de3297c5a3..3ce9f33c57 100644 --- a/percona/k8s/testutils_test.go +++ b/percona/k8s/testutils_test.go @@ -61,7 +61,9 @@ func buildFakeClient(ctx context.Context, cr *v2.PerconaPGCluster, objs ...clien objs = append(objs, dcs) cl := new(fakeClient) - cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...).Build() + cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...). + WithIndex(new(v2.PerconaPGBackup), v2.IndexFieldPGCluster, v2.PGClusterIndexerFunc). + Build() return cl, nil } diff --git a/percona/naming/finalizers.go b/percona/naming/finalizers.go index 604f809b3f..d2fa2858bf 100644 --- a/percona/naming/finalizers.go +++ b/percona/naming/finalizers.go @@ -19,3 +19,8 @@ const ( const ( FinalizerDeleteBackup = PrefixPerconaInternal + "delete-backup" //nolint:gosec ) + +// PerconaPGBackup job finalizers +const ( + FinalizerKeepJob = PrefixPerconaInternal + "keep-job" //nolint:gosec +) From 2f1e9ceede5b608db0508630bc1ba7b9c4a548c8 Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Mon, 26 May 2025 11:28:27 -0300 Subject: [PATCH 034/300] Update codeowners (#1155) Co-authored-by: Viacheslav Sarzhan --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0a105f371a..107e2c58d7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ * @hors @egegunes @pooknull @nmarukovich @gkech -/e2e-tests/ @ptankov @jvpasinatto @eleo007 -Jenkinsfile @ptankov @jvpasinatto @eleo007 +/e2e-tests/ @jvpasinatto @eleo007 @valmiranogueira +Jenkinsfile @jvpasinatto @eleo007 @valmiranogueira From 3b0789c9a4c9b946c9eec0d50a1592b99ebc422e Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 16 Jun 2025 09:24:36 +0300 Subject: [PATCH 035/300] K8SPG-782 assign patroni version to status when patroni label is configured through the cr option (#1165) * K8SPG-782 assign patroni version to status when patroni label is configured through the cr option * cr: add retry on conflict to ensure update when changes happen at the same time * cr: fetch latest cluster using the api --- percona/controller/pgcluster/controller.go | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index b13360340c..c52e5b8625 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -337,6 +337,31 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, if patroniVersion, ok := cr.Annotations[pNaming.AnnotationCustomPatroniVersion]; ok { cr.Annotations[pNaming.AnnotationPatroniVersion] = patroniVersion + + patroniVersionUpdateFunc := func() error { + cluster := &v2.PerconaPGCluster{} + if err := r.Client.Get(ctx, types.NamespacedName{ + Name: cr.Name, + Namespace: cr.Namespace, + }, cluster); err != nil { + return errors.Wrap(err, "get PerconaPGCluster") + } + + orig := cluster.DeepCopy() + + cluster.Status.PatroniVersion = patroniVersion + + if err := r.Client.Status().Patch(ctx, cluster.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "failed to patch patroni version") + } + return nil + } + + // To ensure that the update was done given that conflicts can be caused by + // other code making unrelated updates to the same resource at the same time. + if err := retry.RetryOnConflict(retry.DefaultRetry, patroniVersionUpdateFunc); err != nil { + return errors.Wrap(err, "failed to patch patroni version") + } return nil } From 43879cea8424a45b6882cadf60b222d95cb3be7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 18 Jun 2025 19:54:35 +0300 Subject: [PATCH 036/300] CLOUD-911: Add snyk config (#1168) * CLOUD-911: Add snyk config * add testing * add to e2eignore * add e2eignore to e2eignore --------- Co-authored-by: Viacheslav Sarzhan --- .e2eignore | 4 +++- .snyk | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .snyk diff --git a/.e2eignore b/.e2eignore index c36ff1cacc..c529743135 100644 --- a/.e2eignore +++ b/.e2eignore @@ -7,4 +7,6 @@ CONTRIBUTING.md LICENSE.md README.md .gitignore -release_versions \ No newline at end of file +release_versions +.e2eignore +.snyk diff --git a/.snyk b/.snyk new file mode 100644 index 0000000000..b0b73b3708 --- /dev/null +++ b/.snyk @@ -0,0 +1,10 @@ +#SNYK - percona/percona-postgresql-operator + +exclude: + global: + - e2e-tests/** + - testing/** + +version: v1.25.0 +ignore: {} +patch: {} From 0b8759a811575357309ab4e7d6dbc578a5de976a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Jun 2025 16:39:11 +0300 Subject: [PATCH 037/300] CLOUD-727: Bump google.golang.org/grpc from 1.72.1 to 1.73.0 (#1166) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.1 to 1.73.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.72.1...v1.73.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.73.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 9a6d1d0f0b..ba02e9a64a 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( go.opentelemetry.io/otel/trace v1.35.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.38.0 - google.golang.org/grpc v1.72.1 + google.golang.org/grpc v1.73.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.32.3 k8s.io/apimachinery v0.32.3 @@ -117,7 +117,7 @@ require ( go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.40.0 // indirect - golang.org/x/oauth2 v0.27.0 // indirect + golang.org/x/oauth2 v0.28.0 // indirect golang.org/x/sync v0.14.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/term v0.32.0 // indirect @@ -125,7 +125,7 @@ require ( golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.33.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index a59363e00c..4fb0e19993 100644 --- a/go.sum +++ b/go.sum @@ -302,8 +302,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -360,8 +360,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= +google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 h1:TwXJCGVREgQ/cl18iY0Z4wJCTL/GmW+Um2oSwZiZPnc= google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -369,8 +369,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= +google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= From bc63b33cf739f85f5ba648d874592a7499c46325 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Jun 2025 16:50:50 +0300 Subject: [PATCH 038/300] CLOUD-727: Bump go.opentelemetry.io/otel/sdk from 1.35.0 to 1.36.0 (#1160) Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.35.0 to 1.36.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.35.0...v1.36.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/sdk dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index ba02e9a64a..9ee1627ebd 100644 --- a/go.mod +++ b/go.mod @@ -24,12 +24,12 @@ require ( github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.30.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 - go.opentelemetry.io/otel v1.35.0 + go.opentelemetry.io/otel v1.36.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 - go.opentelemetry.io/otel/sdk v1.35.0 - go.opentelemetry.io/otel/trace v1.35.0 + go.opentelemetry.io/otel/sdk v1.36.0 + go.opentelemetry.io/otel/trace v1.36.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.38.0 google.golang.org/grpc v1.73.0 @@ -113,7 +113,7 @@ require ( go.mongodb.org/mongo-driver v1.14.0 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.40.0 // indirect diff --git a/go.sum b/go.sum index 4fb0e19993..090eb75720 100644 --- a/go.sum +++ b/go.sum @@ -243,22 +243,22 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= From 238a5cc57d2ff7cf2736eebd78d7c27c8df5c473 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 23 Jun 2025 23:36:33 +0300 Subject: [PATCH 039/300] K8SPG-750 fix env var ordering (#1172) --- percona/pmm/pmm.go | 39 ++++++--------------------------------- percona/pmm/pmm_test.go | 12 ++++-------- 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index 27a7a10ecc..0a5e144489 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -58,7 +58,7 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { }) } - container := corev1.Container{ + return corev1.Container{ Name: "pmm-client", Image: pmmSpec.Image, ImagePullPolicy: pmmSpec.ImagePullPolicy, @@ -242,25 +242,6 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { }, }, } - - if pgc.CompareVersion("2.7.0") >= 0 { - clusterName := pgc.Name - if pgc.Spec.PMM.CustomClusterName != "" { - clusterName = pgc.Spec.PMM.CustomClusterName - } - container.Env = append(container.Env, - corev1.EnvVar{ - Name: "CLUSTER_NAME", - Value: clusterName, - }, - corev1.EnvVar{ - Name: "PMM_POSTGRES_PARAMS", - Value: pmmSpec.PostgresParams, - }, - ) - } - - return container } // sidecarContainerV3 refers to the construction of the PMM3 container. @@ -273,10 +254,6 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { } pmmSpec := pgc.Spec.PMM - clusterName := pgc.Name - if pgc.Spec.PMM.CustomClusterName != "" { - clusterName = pgc.Spec.PMM.CustomClusterName - } container := corev1.Container{ Name: "pmm-client", @@ -452,14 +429,6 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { Name: "PMM_AGENT_PATHS_TEMPDIR", Value: "/tmp", }, - { - Name: "CLUSTER_NAME", - Value: clusterName, - }, - { - Name: "PMM_POSTGRES_PARAMS", - Value: pmmSpec.PostgresParams, - }, }, } @@ -486,8 +455,12 @@ func agentPrerunScript(querySource v2.PMMQuerySource, pgc *v2.PerconaPGCluster) } if pgc.CompareVersion("2.7.0") >= 0 { + clusterName := pgc.Name + if pgc.Spec.PMM.CustomClusterName != "" { + clusterName = pgc.Spec.PMM.CustomClusterName + } addServiceArgs = append(addServiceArgs, - "--cluster=$(CLUSTER_NAME)", "$PMM_POSTGRES_PARAMS", + fmt.Sprintf("--cluster=%s", clusterName), pgc.Spec.PMM.PostgresParams, ) } addService := fmt.Sprintf("pmm-admin add postgresql %s", strings.Join(addServiceArgs, " ")) diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index 4502616aad..47b3b6b907 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -179,7 +179,7 @@ func TestSidecarContainerV2(t *testing.T) { assert.NotNil(t, container.Lifecycle.PreStop) assert.Equal(t, []string{"bash", "-c", "pmm-admin unregister --force"}, container.Lifecycle.PreStop.Exec.Command) - assert.Len(t, container.Env, 33) + assert.Len(t, container.Env, 31) expectedEnvVars := map[string]string{ "POD_NAME": "", // field reference is asserted separately @@ -211,10 +211,8 @@ func TestSidecarContainerV2(t *testing.T) { "DB_TYPE": "postgresql", "DB_USER": v2.UserMonitoring, "DB_PASS": "", // secret reference is asserted separately - "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=$(CLUSTER_NAME) $PMM_POSTGRES_PARAMS; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", + "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=test-cluster --environment=dev-postgres; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", "PMM_AGENT_PATHS_TEMPDIR": "/tmp", - "CLUSTER_NAME": "test-cluster", - "PMM_POSTGRES_PARAMS": "--environment=dev-postgres", } for _, envVar := range container.Env { @@ -293,7 +291,7 @@ func TestSidecarContainerV3(t *testing.T) { assert.NotNil(t, container.Lifecycle.PreStop) assert.Equal(t, []string{"bash", "-c", "pmm-admin unregister --force"}, container.Lifecycle.PreStop.Exec.Command) - assert.Len(t, container.Env, 28) + assert.Len(t, container.Env, 26) expectedEnvVars := map[string]string{ "POD_NAME": "", // field reference is asserted separately @@ -320,10 +318,8 @@ func TestSidecarContainerV3(t *testing.T) { "DB_TYPE": "postgresql", "DB_USER": v2.UserMonitoring, "DB_PASS": "", // secret reference is asserted separately - "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=$(CLUSTER_NAME) $PMM_POSTGRES_PARAMS; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", + "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=test-cluster --environment=dev-postgres; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", "PMM_AGENT_PATHS_TEMPDIR": "/tmp", - "CLUSTER_NAME": "test-cluster", - "PMM_POSTGRES_PARAMS": "--environment=dev-postgres", } for _, envVar := range container.Env { From 5f81e5ccd33d58a4c2302b029e88b71df9be298f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 14:57:15 +0300 Subject: [PATCH 040/300] CLOUD-727: Bump k8s.io/apimachinery from 0.32.3 to 0.33.2 (#1173) * CLOUD-727: Bump k8s.io/apimachinery from 0.32.3 to 0.33.2 Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.32.3 to 0.33.2. - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.32.3...v0.33.2) --- updated-dependencies: - dependency-name: k8s.io/apimachinery dependency-version: 0.33.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * golang 1.24 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: George Kechagias --- Jenkinsfile | 2 +- build/postgres-operator/Dockerfile | 2 +- go.mod | 14 +++++++------- go.sum | 23 +++++++++++++---------- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e761d9a3ff..6e6282fa79 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -459,7 +459,7 @@ pipeline { -v $WORKSPACE/src/github.com/percona/percona-postgresql-operator:/go/src/github.com/percona/percona-postgresql-operator \ -w /go/src/github.com/percona/percona-postgresql-operator \ -e GO111MODULE=on \ - golang:1.23 sh -c ' + golang:1.24 sh -c ' go install github.com/google/go-licenses@latest; /go/bin/go-licenses csv github.com/percona/percona-postgresql-operator/cmd/postgres-operator \ | cut -d , -f 3 \ diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index 9ac0654f74..f39296f8a1 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=${BUILDPLATFORM} golang:1.23 AS go_builder +FROM --platform=${BUILDPLATFORM} golang:1.24 AS go_builder WORKDIR /go/src/github.com/percona/percona-postgresql-operator COPY go.mod go.sum ./ diff --git a/go.mod b/go.mod index 9ee1627ebd..cd4ab1e694 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/percona/percona-postgresql-operator -go 1.23.4 +go 1.24.0 toolchain go1.24.1 @@ -35,7 +35,7 @@ require ( google.golang.org/grpc v1.73.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.32.3 - k8s.io/apimachinery v0.32.3 + k8s.io/apimachinery v0.33.2 k8s.io/client-go v0.32.3 k8s.io/component-base v0.32.3 sigs.k8s.io/controller-runtime v0.20.4 @@ -57,6 +57,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect golang.org/x/mod v0.24.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect ) require ( @@ -80,8 +81,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/gofuzz v1.2.0 // indirect + github.com/google/gnostic-models v0.6.9 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 @@ -122,7 +122,7 @@ require ( golang.org/x/sys v0.33.0 // indirect golang.org/x/term v0.32.0 // indirect golang.org/x/text v0.25.0 // indirect - golang.org/x/time v0.8.0 // indirect + golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.33.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect @@ -132,8 +132,8 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.32.3 k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect ) diff --git a/go.sum b/go.sum index 090eb75720..06a7f056f9 100644 --- a/go.sum +++ b/go.sum @@ -91,8 +91,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -335,8 +335,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -402,23 +402,26 @@ k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= -k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= -k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= +k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= -k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA= -sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= From c4df12a0fa2765b85cf9e30fcf3e5f3ddcb2206d Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 25 Jun 2025 12:04:10 +0300 Subject: [PATCH 041/300] K8SPG-798 introduce retry logic on self-healing test (#1181) * K8SPG-798 introduce retry logic on self-healing test * remove errexit --- .../self-healing/07-read-from-all-pods.yaml | 40 +++++++++++++------ .../self-healing/10-read-from-all-pods.yaml | 40 +++++++++++++------ .../self-healing/13-read-from-all-pods.yaml | 40 +++++++++++++------ .../self-healing/16-read-from-all-pods.yaml | 40 +++++++++++++------ 4 files changed, 108 insertions(+), 52 deletions(-) diff --git a/e2e-tests/tests/self-healing/07-read-from-all-pods.yaml b/e2e-tests/tests/self-healing/07-read-from-all-pods.yaml index f16a570527..92f54f5552 100644 --- a/e2e-tests/tests/self-healing/07-read-from-all-pods.yaml +++ b/e2e-tests/tests/self-healing/07-read-from-all-pods.yaml @@ -2,16 +2,30 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep timeout: 30 commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - pods=$(get_instance_set_pods instance1) - i=1 - for pod in $pods; do - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})") - kubectl create configmap -n "${NAMESPACE}" 07-read-from-${i} --from-literal=data="${data}" - i=$((i+1)) - done + - script: |- + set -o xtrace + + source ../../functions + + pods=$(get_instance_set_pods instance1) + i=1 + for pod in $pods; do + set +o xtrace + retry=0 + echo -n "Querying pod ${pod}" + until data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})"); do + sleep 1 + echo -n . + ((retry++)) + if [ $retry -ge 30 ]; then + echo + echo "Max retry count $retry reached on pod ${pod}. Something went wrong." + exit 1 + fi + done + echo + set -o xtrace + + kubectl create configmap -n "${NAMESPACE}" 07-read-from-${i} --from-literal=data="${data}" + i=$((i+1)) + done diff --git a/e2e-tests/tests/self-healing/10-read-from-all-pods.yaml b/e2e-tests/tests/self-healing/10-read-from-all-pods.yaml index 539b75488a..7056435ad3 100644 --- a/e2e-tests/tests/self-healing/10-read-from-all-pods.yaml +++ b/e2e-tests/tests/self-healing/10-read-from-all-pods.yaml @@ -2,16 +2,30 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep timeout: 30 commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - pods=$(get_instance_set_pods instance1) - i=1 - for pod in $pods; do - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})") - kubectl create configmap -n "${NAMESPACE}" 10-read-from-${i} --from-literal=data="${data}" - i=$((i+1)) - done + - script: |- + set -o xtrace + + source ../../functions + + pods=$(get_instance_set_pods instance1) + i=1 + for pod in $pods; do + set +o xtrace + retry=0 + echo -n "Querying pod ${pod}" + until data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})"); do + sleep 1 + echo -n . + ((retry++)) + if [ $retry -ge 30 ]; then + echo + echo "Max retry count $retry reached on pod ${pod}. Something went wrong." + exit 1 + fi + done + echo + set -o xtrace + + kubectl create configmap -n "${NAMESPACE}" 10-read-from-${i} --from-literal=data="${data}" + i=$((i+1)) + done diff --git a/e2e-tests/tests/self-healing/13-read-from-all-pods.yaml b/e2e-tests/tests/self-healing/13-read-from-all-pods.yaml index a83078d0a6..f0eedc7330 100644 --- a/e2e-tests/tests/self-healing/13-read-from-all-pods.yaml +++ b/e2e-tests/tests/self-healing/13-read-from-all-pods.yaml @@ -2,16 +2,30 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep timeout: 30 commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - pods=$(get_instance_set_pods instance1) - i=1 - for pod in $pods; do - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})") - kubectl create configmap -n "${NAMESPACE}" 13-read-from-${i} --from-literal=data="${data}" - i=$((i+1)) - done + - script: |- + set -o xtrace + + source ../../functions + + pods=$(get_instance_set_pods instance1) + i=1 + for pod in $pods; do + set +o xtrace + retry=0 + echo -n "Querying pod ${pod}" + until data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})"); do + sleep 1 + echo -n . + ((retry++)) + if [ $retry -ge 30 ]; then + echo + echo "Max retry count $retry reached on pod ${pod}. Something went wrong." + exit 1 + fi + done + echo + set -o xtrace + + kubectl create configmap -n "${NAMESPACE}" 13-read-from-${i} --from-literal=data="${data}" + i=$((i+1)) + done diff --git a/e2e-tests/tests/self-healing/16-read-from-all-pods.yaml b/e2e-tests/tests/self-healing/16-read-from-all-pods.yaml index 68d789be89..e95754882d 100644 --- a/e2e-tests/tests/self-healing/16-read-from-all-pods.yaml +++ b/e2e-tests/tests/self-healing/16-read-from-all-pods.yaml @@ -2,16 +2,30 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep timeout: 30 commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - pods=$(get_instance_set_pods instance1) - i=1 - for pod in $pods; do - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})") - kubectl create configmap -n "${NAMESPACE}" 16-read-from-${i} --from-literal=data="${data}" - i=$((i+1)) - done + - script: |- + set -o xtrace + + source ../../functions + + pods=$(get_instance_set_pods instance1) + i=1 + for pod in $pods; do + set +o xtrace + retry=0 + echo -n "Querying pod ${pod}" + until data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass self-healing-pguser-postgres)@$(get_psql_pod_host ${pod})"); do + sleep 1 + echo -n . + ((retry++)) + if [ $retry -ge 30 ]; then + echo + echo "Max retry count $retry reached on pod ${pod}. Something went wrong." + exit 1 + fi + done + echo + set -o xtrace + + kubectl create configmap -n "${NAMESPACE}" 16-read-from-${i} --from-literal=data="${data}" + i=$((i+1)) + done From 0bc062a93abfa00f46349e1748d8ecb8b77add1c Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Wed, 25 Jun 2025 14:22:20 +0300 Subject: [PATCH 042/300] K8SPG-703: add missing ttlSecondsAfterFinished field (#1180) https://perconadev.atlassian.net/browse/K8SPG-703 Co-authored-by: George Kechagias --- deploy/cr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 5e9781730e..638faec75b 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -422,6 +422,7 @@ spec: # restartPolicy: OnFailure # backoffLimit: 2 # priorityClassName: high-priority +# ttlSecondsAfterFinished: 60 # resources: # limits: # cpu: 200m From 02cb95c196a93ff03ce0442bb65af1f1fe9f0505 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 17:46:29 +0300 Subject: [PATCH 043/300] CLOUD-727: Bump sigs.k8s.io/controller-runtime from 0.20.4 to 0.21.0 (#1179) * CLOUD-727: Bump sigs.k8s.io/controller-runtime from 0.20.4 to 0.21.0 Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.20.4 to 0.21.0. - [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.20.4...v0.21.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-runtime dependency-version: 0.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * run make generate main --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: George Kechagias --- ...ator.crunchydata.com_postgresclusters.yaml | 108 ++------ .../pgv2.percona.com_perconapgclusters.yaml | 98 ++----- .../pgv2.percona.com_perconapgupgrades.yaml | 20 +- .../pgv2.percona.com_perconapgclusters.yaml | 118 +++----- ...res-operator.crunchydata.com_pgadmins.yaml | 8 - ...s-operator.crunchydata.com_pgupgrades.yaml | 20 +- ...ator.crunchydata.com_postgresclusters.yaml | 108 ++------ deploy/bundle.yaml | 254 +++++------------- deploy/crd.yaml | 254 +++++------------- deploy/cw-bundle.yaml | 254 +++++------------- go.mod | 18 +- go.sum | 42 ++- 12 files changed, 379 insertions(+), 923 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 39e54898c7..3e527f75fd 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -944,7 +944,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -959,7 +958,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1128,7 +1126,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1143,7 +1140,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1310,7 +1306,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1325,7 +1320,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1494,7 +1488,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1509,7 +1502,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2287,7 +2279,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2302,7 +2293,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2471,7 +2461,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2486,7 +2475,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2653,7 +2641,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2668,7 +2655,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2837,7 +2823,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2852,7 +2837,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3522,7 +3506,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -3533,7 +3516,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -4168,7 +4150,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4183,7 +4164,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4352,7 +4332,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4367,7 +4346,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4534,7 +4512,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4549,7 +4526,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4718,7 +4694,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4733,7 +4708,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5915,7 +5889,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5930,7 +5903,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6098,7 +6070,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6113,7 +6084,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6279,7 +6249,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6294,7 +6263,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6462,7 +6430,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6477,7 +6444,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7605,7 +7571,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7620,7 +7585,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7788,7 +7752,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7803,7 +7766,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7969,7 +7931,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7984,7 +7945,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8152,7 +8112,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8167,7 +8126,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9224,7 +9182,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9239,7 +9196,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9406,7 +9362,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9421,7 +9376,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9586,7 +9540,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9601,7 +9554,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9768,7 +9720,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9783,7 +9734,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10037,7 +9987,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10058,8 +10008,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10323,6 +10273,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -11935,7 +11891,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -11956,8 +11912,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -12221,6 +12177,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -13992,7 +13954,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -14003,7 +13964,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -15202,7 +15162,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15217,7 +15176,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15385,7 +15343,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15400,7 +15357,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15566,7 +15522,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15581,7 +15536,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15749,7 +15703,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15764,7 +15717,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16386,7 +16338,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -16407,8 +16359,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -16674,6 +16626,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -18347,7 +18305,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -18358,7 +18315,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -18851,7 +18807,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -18866,7 +18821,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19034,7 +18988,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19049,7 +19002,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19215,7 +19167,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19230,7 +19181,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19398,7 +19348,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19413,7 +19362,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20375,7 +20323,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -20386,7 +20333,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 3b0dfd5196..67692654b2 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -1102,7 +1102,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1117,7 +1116,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1286,7 +1284,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1301,7 +1298,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1468,7 +1464,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1483,7 +1478,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1652,7 +1646,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1667,7 +1660,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2445,7 +2437,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2460,7 +2451,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2629,7 +2619,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2644,7 +2633,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2811,7 +2799,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2826,7 +2813,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2995,7 +2981,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3010,7 +2995,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3680,7 +3664,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -3691,7 +3674,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -4326,7 +4308,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4341,7 +4322,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4510,7 +4490,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4525,7 +4504,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4692,7 +4670,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4707,7 +4684,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4876,7 +4852,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4891,7 +4866,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5563,7 +5537,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5578,7 +5551,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5746,7 +5718,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5761,7 +5732,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5927,7 +5897,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5942,7 +5911,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6110,7 +6078,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6125,7 +6092,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7253,7 +7219,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7268,7 +7233,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7436,7 +7400,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7451,7 +7414,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7617,7 +7579,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7632,7 +7593,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7800,7 +7760,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7815,7 +7774,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9029,7 +8987,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9044,7 +9001,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9211,7 +9167,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9226,7 +9181,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9391,7 +9345,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9406,7 +9359,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9573,7 +9525,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9588,7 +9539,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10374,7 +10324,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10395,8 +10345,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10660,6 +10610,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -12142,7 +12098,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -12163,8 +12119,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -12428,6 +12384,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -13797,7 +13759,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -13808,7 +13769,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -14827,7 +14787,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -14842,7 +14801,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15010,7 +14968,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15025,7 +14982,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15191,7 +15147,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15206,7 +15161,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15374,7 +15328,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15389,7 +15342,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16522,7 +16474,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -16543,8 +16495,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -16810,6 +16762,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -17956,7 +17914,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -17967,7 +17924,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml index b44748b1d1..4d8151b507 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml @@ -324,7 +324,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -339,7 +338,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -505,7 +503,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -520,7 +517,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -683,7 +679,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -698,7 +693,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -864,7 +858,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -879,7 +872,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1169,7 +1161,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -1190,8 +1182,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -1454,6 +1446,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 1b97dff6da..5f52ac97d6 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -1509,7 +1509,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1524,7 +1523,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1693,7 +1691,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1708,7 +1705,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1875,7 +1871,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1890,7 +1885,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2059,7 +2053,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2074,7 +2067,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2852,7 +2844,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2867,7 +2858,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3036,7 +3026,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3051,7 +3040,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3218,7 +3206,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3233,7 +3220,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3402,7 +3388,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3417,7 +3402,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4087,7 +4071,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -4098,7 +4081,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -4733,7 +4715,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4748,7 +4729,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4917,7 +4897,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4932,7 +4911,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5099,7 +5077,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5114,7 +5091,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5283,7 +5259,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5298,7 +5273,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5970,7 +5944,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5985,7 +5958,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6153,7 +6125,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6168,7 +6139,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6334,7 +6304,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6349,7 +6318,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6517,7 +6485,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6532,7 +6499,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7660,7 +7626,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7675,7 +7640,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7843,7 +7807,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7858,7 +7821,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8024,7 +7986,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8039,7 +8000,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8207,7 +8167,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8222,7 +8181,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9436,7 +9394,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9451,7 +9408,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9618,7 +9574,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9633,7 +9588,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9798,7 +9752,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9813,7 +9766,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9980,7 +9932,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9995,7 +9946,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10781,7 +10731,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10802,8 +10752,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -11067,6 +11017,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -12549,7 +12505,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -12570,8 +12526,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -12835,6 +12791,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -14204,7 +14166,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -14215,7 +14176,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -15234,7 +15194,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15249,7 +15208,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15417,7 +15375,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15432,7 +15389,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15598,7 +15554,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15613,7 +15568,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15781,7 +15735,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15796,7 +15749,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16929,7 +16881,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -16950,8 +16902,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -17217,6 +17169,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -18363,7 +18321,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -18374,7 +18331,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -19269,7 +19225,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19284,7 +19239,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19450,7 +19404,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19465,7 +19418,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19628,7 +19580,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19643,7 +19594,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19809,7 +19759,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19824,7 +19773,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20114,7 +20062,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -20135,8 +20083,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -20399,6 +20347,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml index 0a3d60b7c0..f2b51f4ee6 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml @@ -327,7 +327,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -342,7 +341,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -508,7 +506,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -523,7 +520,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -686,7 +682,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -701,7 +696,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -867,7 +861,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -882,7 +875,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml index 46b28a9a75..2e9319c8cc 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml @@ -327,7 +327,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -342,7 +341,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -508,7 +506,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -523,7 +520,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -686,7 +682,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -701,7 +696,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -867,7 +861,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -882,7 +875,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1167,7 +1159,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -1188,8 +1180,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -1452,6 +1444,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 06707c0f2f..74d4c1ef1d 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -936,7 +936,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -951,7 +950,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1120,7 +1118,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1135,7 +1132,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1302,7 +1298,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1317,7 +1312,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1486,7 +1480,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1501,7 +1494,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2279,7 +2271,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2294,7 +2285,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2463,7 +2453,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2478,7 +2467,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2645,7 +2633,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2660,7 +2647,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2829,7 +2815,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2844,7 +2829,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3504,7 +3488,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -3515,7 +3498,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -4158,7 +4140,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4173,7 +4154,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4342,7 +4322,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4357,7 +4336,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4524,7 +4502,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4539,7 +4516,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4708,7 +4684,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4723,7 +4698,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5885,7 +5859,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5900,7 +5873,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6068,7 +6040,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6083,7 +6054,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6249,7 +6219,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6264,7 +6233,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6432,7 +6400,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6447,7 +6414,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7565,7 +7531,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7580,7 +7545,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7748,7 +7712,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7763,7 +7726,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7929,7 +7891,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7944,7 +7905,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8112,7 +8072,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8127,7 +8086,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9179,7 +9137,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9194,7 +9151,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9361,7 +9317,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9376,7 +9331,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9541,7 +9495,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9556,7 +9509,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9723,7 +9675,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9738,7 +9689,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9984,7 +9934,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -10001,8 +9951,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -10258,6 +10208,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -11877,7 +11833,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -11898,8 +11854,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -12163,6 +12119,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -13934,7 +13896,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -13945,7 +13906,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -15144,7 +15104,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15159,7 +15118,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15327,7 +15285,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15342,7 +15299,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15508,7 +15464,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15523,7 +15478,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15691,7 +15645,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15706,7 +15659,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16312,7 +16264,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -16329,8 +16281,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -16588,6 +16540,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -18256,7 +18214,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -18267,7 +18224,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -18762,7 +18718,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -18777,7 +18732,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -18945,7 +18899,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -18960,7 +18913,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19126,7 +19078,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19141,7 +19092,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19309,7 +19259,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19324,7 +19273,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20273,7 +20221,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -20284,7 +20231,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 0768919028..b23cab131a 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -1806,7 +1806,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1821,7 +1820,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1990,7 +1988,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2005,7 +2002,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2172,7 +2168,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2187,7 +2182,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2356,7 +2350,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2371,7 +2364,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3149,7 +3141,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3164,7 +3155,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3333,7 +3323,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3348,7 +3337,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3515,7 +3503,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3530,7 +3517,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3699,7 +3685,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3714,7 +3699,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4384,7 +4368,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -4395,7 +4378,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -5030,7 +5012,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5045,7 +5026,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5214,7 +5194,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5229,7 +5208,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5396,7 +5374,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5411,7 +5388,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5580,7 +5556,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5595,7 +5570,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6267,7 +6241,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6282,7 +6255,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6450,7 +6422,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6465,7 +6436,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6631,7 +6601,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6646,7 +6615,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6814,7 +6782,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6829,7 +6796,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7957,7 +7923,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7972,7 +7937,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8140,7 +8104,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8155,7 +8118,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8321,7 +8283,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8336,7 +8297,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8504,7 +8464,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8519,7 +8478,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9733,7 +9691,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9748,7 +9705,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9915,7 +9871,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9930,7 +9885,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10095,7 +10049,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10110,7 +10063,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10277,7 +10229,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10292,7 +10243,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -11078,7 +11028,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -11099,8 +11049,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -11364,6 +11314,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -12846,7 +12802,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -12867,8 +12823,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13132,6 +13088,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -14501,7 +14463,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -14512,7 +14473,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -15531,7 +15491,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15546,7 +15505,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15714,7 +15672,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15729,7 +15686,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15895,7 +15851,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15910,7 +15865,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16078,7 +16032,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16093,7 +16046,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -17226,7 +17178,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -17247,8 +17199,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -17514,6 +17466,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -18660,7 +18618,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -18671,7 +18628,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -19568,7 +19524,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19583,7 +19538,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19749,7 +19703,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19764,7 +19717,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19927,7 +19879,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19942,7 +19893,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20108,7 +20058,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20123,7 +20072,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20413,7 +20361,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -20434,8 +20382,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -20698,6 +20646,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -22284,7 +22238,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22299,7 +22252,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22465,7 +22417,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22480,7 +22431,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22643,7 +22593,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22658,7 +22607,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22824,7 +22772,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22839,7 +22786,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24188,7 +24134,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24203,7 +24148,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24369,7 +24313,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24384,7 +24327,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24547,7 +24489,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24562,7 +24503,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24728,7 +24668,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24743,7 +24682,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -25028,7 +24966,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -25049,8 +24987,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -25313,6 +25251,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -27498,7 +27442,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27513,7 +27456,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27682,7 +27624,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27697,7 +27638,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27864,7 +27804,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27879,7 +27818,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28048,7 +27986,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28063,7 +28000,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28841,7 +28777,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28856,7 +28791,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29025,7 +28959,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29040,7 +28973,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29207,7 +29139,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29222,7 +29153,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29391,7 +29321,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29406,7 +29335,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30066,7 +29994,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -30077,7 +30004,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -30720,7 +30646,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30735,7 +30660,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30904,7 +30828,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30919,7 +30842,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31086,7 +31008,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31101,7 +31022,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31270,7 +31190,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31285,7 +31204,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32447,7 +32365,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32462,7 +32379,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32630,7 +32546,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32645,7 +32560,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32811,7 +32725,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32826,7 +32739,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32994,7 +32906,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -33009,7 +32920,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34127,7 +34037,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34142,7 +34051,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34310,7 +34218,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34325,7 +34232,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34491,7 +34397,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34506,7 +34411,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34674,7 +34578,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34689,7 +34592,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35741,7 +35643,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35756,7 +35657,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35923,7 +35823,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35938,7 +35837,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36103,7 +36001,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36118,7 +36015,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36285,7 +36181,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36300,7 +36195,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36546,7 +36440,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -36563,8 +36457,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -36820,6 +36714,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -38439,7 +38339,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -38460,8 +38360,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -38725,6 +38625,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -40496,7 +40402,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -40507,7 +40412,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -41706,7 +41610,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41721,7 +41624,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41889,7 +41791,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41904,7 +41805,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42070,7 +41970,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42085,7 +41984,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42253,7 +42151,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42268,7 +42165,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42874,7 +42770,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -42891,8 +42787,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -43150,6 +43046,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -44818,7 +44720,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -44829,7 +44730,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -45324,7 +45224,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45339,7 +45238,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45507,7 +45405,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45522,7 +45419,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45688,7 +45584,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45703,7 +45598,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45871,7 +45765,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45886,7 +45779,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -46835,7 +46727,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -46846,7 +46737,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- diff --git a/deploy/crd.yaml b/deploy/crd.yaml index bd5bd24781..19de1e5f34 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -1806,7 +1806,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1821,7 +1820,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1990,7 +1988,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2005,7 +2002,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2172,7 +2168,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2187,7 +2182,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2356,7 +2350,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2371,7 +2364,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3149,7 +3141,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3164,7 +3155,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3333,7 +3323,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3348,7 +3337,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3515,7 +3503,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3530,7 +3517,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3699,7 +3685,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3714,7 +3699,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4384,7 +4368,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -4395,7 +4378,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -5030,7 +5012,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5045,7 +5026,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5214,7 +5194,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5229,7 +5208,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5396,7 +5374,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5411,7 +5388,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5580,7 +5556,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5595,7 +5570,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6267,7 +6241,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6282,7 +6255,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6450,7 +6422,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6465,7 +6436,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6631,7 +6601,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6646,7 +6615,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6814,7 +6782,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6829,7 +6796,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7957,7 +7923,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7972,7 +7937,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8140,7 +8104,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8155,7 +8118,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8321,7 +8283,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8336,7 +8297,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8504,7 +8464,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8519,7 +8478,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9733,7 +9691,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9748,7 +9705,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9915,7 +9871,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9930,7 +9885,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10095,7 +10049,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10110,7 +10063,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10277,7 +10229,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10292,7 +10243,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -11078,7 +11028,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -11099,8 +11049,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -11364,6 +11314,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -12846,7 +12802,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -12867,8 +12823,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13132,6 +13088,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -14501,7 +14463,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -14512,7 +14473,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -15531,7 +15491,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15546,7 +15505,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15714,7 +15672,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15729,7 +15686,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15895,7 +15851,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15910,7 +15865,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16078,7 +16032,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16093,7 +16046,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -17226,7 +17178,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -17247,8 +17199,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -17514,6 +17466,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -18660,7 +18618,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -18671,7 +18628,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -19568,7 +19524,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19583,7 +19538,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19749,7 +19703,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19764,7 +19717,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19927,7 +19879,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19942,7 +19893,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20108,7 +20058,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20123,7 +20072,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20413,7 +20361,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -20434,8 +20382,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -20698,6 +20646,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -22284,7 +22238,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22299,7 +22252,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22465,7 +22417,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22480,7 +22431,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22643,7 +22593,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22658,7 +22607,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22824,7 +22772,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22839,7 +22786,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24188,7 +24134,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24203,7 +24148,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24369,7 +24313,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24384,7 +24327,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24547,7 +24489,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24562,7 +24503,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24728,7 +24668,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24743,7 +24682,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -25028,7 +24966,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -25049,8 +24987,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -25313,6 +25251,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -27498,7 +27442,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27513,7 +27456,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27682,7 +27624,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27697,7 +27638,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27864,7 +27804,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27879,7 +27818,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28048,7 +27986,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28063,7 +28000,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28841,7 +28777,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28856,7 +28791,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29025,7 +28959,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29040,7 +28973,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29207,7 +29139,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29222,7 +29153,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29391,7 +29321,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29406,7 +29335,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30066,7 +29994,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -30077,7 +30004,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -30720,7 +30646,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30735,7 +30660,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30904,7 +30828,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30919,7 +30842,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31086,7 +31008,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31101,7 +31022,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31270,7 +31190,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31285,7 +31204,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32447,7 +32365,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32462,7 +32379,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32630,7 +32546,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32645,7 +32560,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32811,7 +32725,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32826,7 +32739,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32994,7 +32906,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -33009,7 +32920,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34127,7 +34037,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34142,7 +34051,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34310,7 +34218,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34325,7 +34232,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34491,7 +34397,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34506,7 +34411,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34674,7 +34578,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34689,7 +34592,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35741,7 +35643,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35756,7 +35657,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35923,7 +35823,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35938,7 +35837,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36103,7 +36001,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36118,7 +36015,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36285,7 +36181,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36300,7 +36195,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36546,7 +36440,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -36563,8 +36457,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -36820,6 +36714,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -38439,7 +38339,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -38460,8 +38360,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -38725,6 +38625,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -40496,7 +40402,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -40507,7 +40412,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -41706,7 +41610,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41721,7 +41624,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41889,7 +41791,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41904,7 +41805,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42070,7 +41970,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42085,7 +41984,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42253,7 +42151,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42268,7 +42165,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42874,7 +42770,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -42891,8 +42787,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -43150,6 +43046,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -44818,7 +44720,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -44829,7 +44730,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -45324,7 +45224,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45339,7 +45238,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45507,7 +45405,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45522,7 +45419,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45688,7 +45584,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45703,7 +45598,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45871,7 +45765,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45886,7 +45779,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -46835,7 +46727,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -46846,7 +46737,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 0c16506f0d..2c3b64903b 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -1806,7 +1806,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1821,7 +1820,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1990,7 +1988,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2005,7 +2002,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2172,7 +2168,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2187,7 +2182,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2356,7 +2350,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -2371,7 +2364,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3149,7 +3141,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3164,7 +3155,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3333,7 +3323,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3348,7 +3337,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3515,7 +3503,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3530,7 +3517,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3699,7 +3685,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -3714,7 +3699,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -4384,7 +4368,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -4395,7 +4378,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -5030,7 +5012,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5045,7 +5026,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5214,7 +5194,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5229,7 +5208,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5396,7 +5374,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5411,7 +5388,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5580,7 +5556,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -5595,7 +5570,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6267,7 +6241,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6282,7 +6255,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6450,7 +6422,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6465,7 +6436,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6631,7 +6601,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6646,7 +6615,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6814,7 +6782,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -6829,7 +6796,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7957,7 +7923,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -7972,7 +7937,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8140,7 +8104,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8155,7 +8118,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8321,7 +8283,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8336,7 +8297,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8504,7 +8464,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8519,7 +8478,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9733,7 +9691,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9748,7 +9705,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9915,7 +9871,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -9930,7 +9885,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10095,7 +10049,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10110,7 +10063,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10277,7 +10229,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -10292,7 +10243,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -11078,7 +11028,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -11099,8 +11049,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -11364,6 +11314,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -12846,7 +12802,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -12867,8 +12823,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -13132,6 +13088,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -14501,7 +14463,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -14512,7 +14473,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -15531,7 +15491,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15546,7 +15505,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15714,7 +15672,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15729,7 +15686,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15895,7 +15851,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -15910,7 +15865,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16078,7 +16032,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -16093,7 +16046,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -17226,7 +17178,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -17247,8 +17199,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -17514,6 +17466,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -18660,7 +18618,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -18671,7 +18628,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -19568,7 +19524,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19583,7 +19538,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19749,7 +19703,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19764,7 +19717,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19927,7 +19879,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -19942,7 +19893,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20108,7 +20058,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20123,7 +20072,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -20413,7 +20361,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -20434,8 +20382,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -20698,6 +20646,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -22284,7 +22238,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22299,7 +22252,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22465,7 +22417,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22480,7 +22431,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22643,7 +22593,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22658,7 +22607,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22824,7 +22772,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -22839,7 +22786,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24188,7 +24134,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24203,7 +24148,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24369,7 +24313,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24384,7 +24327,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24547,7 +24489,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24562,7 +24503,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24728,7 +24668,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -24743,7 +24682,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -25028,7 +24966,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of a set - of ConfigMaps + of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -25049,8 +24987,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to each - key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -25313,6 +25251,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -27498,7 +27442,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27513,7 +27456,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27682,7 +27624,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27697,7 +27638,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27864,7 +27804,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -27879,7 +27818,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28048,7 +27986,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28063,7 +28000,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28841,7 +28777,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -28856,7 +28791,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29025,7 +28959,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29040,7 +28973,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29207,7 +29139,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29222,7 +29153,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29391,7 +29321,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -29406,7 +29335,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30066,7 +29994,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -30077,7 +30004,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -30720,7 +30646,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30735,7 +30660,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30904,7 +30828,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -30919,7 +30842,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31086,7 +31008,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31101,7 +31022,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31270,7 +31190,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -31285,7 +31204,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32447,7 +32365,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32462,7 +32379,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32630,7 +32546,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32645,7 +32560,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32811,7 +32725,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32826,7 +32739,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -32994,7 +32906,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -33009,7 +32920,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34127,7 +34037,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34142,7 +34051,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34310,7 +34218,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34325,7 +34232,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34491,7 +34397,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34506,7 +34411,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34674,7 +34578,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -34689,7 +34592,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35741,7 +35643,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35756,7 +35657,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35923,7 +35823,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -35938,7 +35837,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36103,7 +36001,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36118,7 +36015,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36285,7 +36181,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36300,7 +36195,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -36546,7 +36440,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -36563,8 +36457,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -36820,6 +36714,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -38439,7 +38339,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -38460,8 +38360,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend to - each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -38725,6 +38625,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -40496,7 +40402,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -40507,7 +40412,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -41706,7 +41610,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41721,7 +41624,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41889,7 +41791,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -41904,7 +41805,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42070,7 +41970,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42085,7 +41984,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42253,7 +42151,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42268,7 +42165,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -42874,7 +42770,7 @@ spec: Cannot be updated. items: description: EnvFromSource represents the source of - a set of ConfigMaps + a set of ConfigMaps or Secrets properties: configMapRef: description: The ConfigMap to select from @@ -42891,8 +42787,8 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: An optional identifier to prepend - to each key in the ConfigMap. Must be a C_IDENTIFIER. + description: Optional text to prepend to the name + of each environment variable. Must be a C_IDENTIFIER. type: string secretRef: description: The Secret to select from @@ -43150,6 +43046,12 @@ spec: - port type: object type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string type: object livenessProbe: description: |- @@ -44818,7 +44720,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -44829,7 +44730,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- @@ -45324,7 +45224,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45339,7 +45238,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45507,7 +45405,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45522,7 +45419,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45688,7 +45584,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45703,7 +45598,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45871,7 +45765,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both matchLabelKeys and labelSelector. Also, matchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -45886,7 +45779,6 @@ spec: pod labels will be ignored. The default value is empty. The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -46835,7 +46727,6 @@ spec: - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. If this value is nil, the behavior is equivalent to the Honor policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string nodeTaintsPolicy: description: |- @@ -46846,7 +46737,6 @@ spec: - Ignore: node taints are ignored. All nodes are included. If this value is nil, the behavior is equivalent to the Ignore policy. - This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string topologyKey: description: |- diff --git a/go.mod b/go.mod index cd4ab1e694..789360638d 100644 --- a/go.mod +++ b/go.mod @@ -34,11 +34,11 @@ require ( golang.org/x/crypto v0.38.0 google.golang.org/grpc v1.73.0 gotest.tools/v3 v3.5.2 - k8s.io/api v0.32.3 + k8s.io/api v0.33.0 k8s.io/apimachinery v0.33.2 - k8s.io/client-go v0.32.3 - k8s.io/component-base v0.32.3 - sigs.k8s.io/controller-runtime v0.20.4 + k8s.io/client-go v0.33.0 + k8s.io/component-base v0.33.0 + sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.4.0 ) @@ -48,10 +48,8 @@ require ( github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/btree v1.1.3 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect - github.com/spf13/cobra v1.8.1 // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect @@ -98,9 +96,9 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/robfig/cron/v3 v3.0.1 github.com/sergi/go-diff v1.3.1 // indirect @@ -130,7 +128,7 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.32.3 + k8s.io/apiextensions-apiserver v0.33.0 k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 diff --git a/go.sum b/go.sum index 06a7f056f9..fb8145441d 100644 --- a/go.sum +++ b/go.sum @@ -24,7 +24,6 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -105,8 +104,8 @@ github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= @@ -115,8 +114,6 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -127,6 +124,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -137,6 +136,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 h1:Q3jQ1NkFqv5o+F8dMmHd8SfEmlcwNeo1immFApntEwE= github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= @@ -179,20 +180,19 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -200,8 +200,6 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -398,24 +396,24 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= -k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= -k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY= -k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss= +k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU= +k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM= +k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs= +k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc= k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= -k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= -k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k= -k8s.io/component-base v0.32.3/go.mod h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI= +k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98= +k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg= +k8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk= +k8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU= -sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY= +sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= +sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= From 001be491ce56cb5de7b274dfcc0e93b15f37bf5c Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 27 Jun 2025 16:01:10 +0300 Subject: [PATCH 044/300] K8SPG-803 specify log level info when pgbackrest is executed through cli - GetInfo (#1186) --- e2e-tests/tests/demand-backup/01-create-cluster.yaml | 1 + .../tests/demand-backup/05-check-pgbackrest-info-s3.yaml | 2 +- .../demand-backup/07-check-pgbackrest-info-azure.yaml | 2 +- e2e-tests/tests/demand-backup/18-create-restore-s3.yaml | 2 +- .../tests/demand-backup/21-create-restore-azure.yaml | 2 +- percona/pgbackrest/pgbackrest.go | 8 +++++++- 6 files changed, 12 insertions(+), 5 deletions(-) diff --git a/e2e-tests/tests/demand-backup/01-create-cluster.yaml b/e2e-tests/tests/demand-backup/01-create-cluster.yaml index 4f21b0cc17..9fb830c946 100644 --- a/e2e-tests/tests/demand-backup/01-create-cluster.yaml +++ b/e2e-tests/tests/demand-backup/01-create-cluster.yaml @@ -10,6 +10,7 @@ commands: get_cr "demand-backup" ${RANDOM} \ | yq '.metadata.finalizers=["percona.com/delete-backups"]' \ + | yq '.spec.backups.pgbackrest.global.log-level-console="debug"' \ | yq '.spec.backups.pgbackrest.global.repo1-retention-full="2"' \ | yq '.spec.backups.pgbackrest.global.repo1-retention-full-type="count"' \ | yq '.spec.backups.pgbackrest.global.repo3-retention-full="2"' \ diff --git a/e2e-tests/tests/demand-backup/05-check-pgbackrest-info-s3.yaml b/e2e-tests/tests/demand-backup/05-check-pgbackrest-info-s3.yaml index 019600f9f2..c670e71969 100644 --- a/e2e-tests/tests/demand-backup/05-check-pgbackrest-info-s3.yaml +++ b/e2e-tests/tests/demand-backup/05-check-pgbackrest-info-s3.yaml @@ -9,7 +9,7 @@ commands: instance=$(kubectl get -n "${NAMESPACE}" pod -l postgres-operator.crunchydata.com/instance-set=instance1 -o 'jsonpath={.items[].metadata.name}') - pgbackrest_info_backups=$(kubectl exec -n "${NAMESPACE}" "$instance" -c database -- pgbackrest info --output json | jq '.[0].backup[]') + pgbackrest_info_backups=$(kubectl exec -n "${NAMESPACE}" "$instance" -c database -- pgbackrest info --output json --log-level-console=info | jq '.[0].backup[]') check_backup() { local backup_name=$1 diff --git a/e2e-tests/tests/demand-backup/07-check-pgbackrest-info-azure.yaml b/e2e-tests/tests/demand-backup/07-check-pgbackrest-info-azure.yaml index 2f55785e32..72f00c43c2 100644 --- a/e2e-tests/tests/demand-backup/07-check-pgbackrest-info-azure.yaml +++ b/e2e-tests/tests/demand-backup/07-check-pgbackrest-info-azure.yaml @@ -9,7 +9,7 @@ commands: instance=$(kubectl get -n "${NAMESPACE}" pod -l postgres-operator.crunchydata.com/instance-set=instance1 -o 'jsonpath={.items[].metadata.name}') - pgbackrest_info_backups=$(kubectl exec -n "${NAMESPACE}" "$instance" -c database -- pgbackrest info --output json | jq '.[0].backup[]') + pgbackrest_info_backups=$(kubectl exec -n "${NAMESPACE}" "$instance" -c database -- pgbackrest info --output json --log-level-console=info | jq '.[0].backup[]') check_backup() { local backup_name=$1 diff --git a/e2e-tests/tests/demand-backup/18-create-restore-s3.yaml b/e2e-tests/tests/demand-backup/18-create-restore-s3.yaml index 20ae096fed..c999ed4761 100644 --- a/e2e-tests/tests/demand-backup/18-create-restore-s3.yaml +++ b/e2e-tests/tests/demand-backup/18-create-restore-s3.yaml @@ -8,7 +8,7 @@ commands: source ../../functions primary=$(get_pod_by_role demand-backup primary name) - latest_full_repo1_backup=$(kubectl -n ${NAMESPACE} exec ${primary} -- pgbackrest info --output json | jq '[.[] | .backup[] | select(.type == "full") | select(.database.["repo-key"] == 1)][-1].label') + latest_full_repo1_backup=$(kubectl -n ${NAMESPACE} exec ${primary} -- pgbackrest info --output json --log-level-console=info | jq '[.[] | .backup[] | select(.type == "full") | select(.database.["repo-key"] == 1)][-1].label') cat < Date: Sat, 28 Jun 2025 10:00:43 +0300 Subject: [PATCH 045/300] K8SPG 798 remove watch secrets unit test (#1183) * K8SPG-798 fix for watching secret env test * remove test completely * fix imports --------- Co-authored-by: Viacheslav Sarzhan --- .../controller/pgcluster/controller_test.go | 225 ------------------ 1 file changed, 225 deletions(-) diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 92bfb7a3d8..3d91d4edb2 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -7,9 +7,7 @@ import ( "context" "crypto/md5" //nolint:gosec "fmt" - "os" "strconv" - "sync" "time" . "github.com/onsi/ginkgo/v2" @@ -25,15 +23,10 @@ import ( "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - metricsServer "sigs.k8s.io/controller-runtime/pkg/metrics/server" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - internalRuntime "github.com/percona/percona-postgresql-operator/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/naming" - perconaController "github.com/percona/percona-postgresql-operator/percona/controller" pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/runtime" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -504,224 +497,6 @@ func (t *tracerWithCounter) Start(ctx context.Context, spanName string, opts ... return ctx, span } -func getReconcileCount(r *postgrescluster.Reconciler) int { - return r.Tracer.(*tracerWithCounter).counter -} - -var _ = Describe("Watching secrets", Ordered, func() { - ctx := context.Background() - - const crName = "watch-secret-test" - const ns = crName - - crunchyR := crunchyReconciler() - r := reconciler(&v2.PerconaPGCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: crName, - Namespace: ns, - }, - }) - - namespace := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: crName, - Namespace: ns, - }, - } - - mgrCtx, cancel := context.WithCancel(ctx) - wg := sync.WaitGroup{} - - BeforeAll(func() { - By("Creating the Namespace to perform the tests") - err := k8sClient.Create(ctx, namespace) - Expect(err).NotTo(HaveOccurred()) - - gate := feature.NewGate() - err = gate.SetFromMap(map[string]bool{}) - Expect(err).NotTo(HaveOccurred()) - - Expect(err).To(Not(HaveOccurred())) - - os.Setenv("PGO_TARGET_NAMESPACE", "") - mgr, err := runtime.CreateRuntimeManager(cfg, gate, internalRuntime.Options{ - LeaderElection: false, - HealthProbeBindAddress: "0", - Metrics: metricsServer.Options{ - BindAddress: "0", - }, - }) - Expect(err).To(Succeed()) - Expect(v2.AddToScheme(mgr.GetScheme())).To(Succeed()) - - r.Client = mgr.GetClient() - crunchyR.Client = mgr.GetClient() - crunchyR.Tracer = &tracerWithCounter{t: crunchyR.Tracer} - - cm := &perconaController.CustomManager{Manager: mgr} - Expect(crunchyR.SetupWithManager(cm)).To(Succeed()) - - Expect(cm.Controller()).NotTo(BeNil()) - r.CrunchyController = cm.Controller() - Expect(r.SetupWithManager(mgr)).To(Succeed()) - - wg.Add(1) - go func() { - Expect(mgr.Start(mgrCtx)).To(Succeed()) - wg.Done() - }() - }) - - AfterAll(func() { - By("Stopping manager") - cancel() - wg.Wait() - - By("Deleting the Namespace to perform the tests") - _ = k8sClient.Delete(ctx, namespace) - }) - - cr, err := readDefaultCR(crName, ns) - It("should read default cr.yaml", func() { - Expect(err).NotTo(HaveOccurred()) - }) - for i := range cr.Spec.Backups.PGBackRest.Repos { - cr.Spec.Backups.PGBackRest.Repos[i].BackupSchedules = nil - } - - reconcileCount := 0 - Context("Create cluster and wait until Reconcile stops", func() { - It("should create PerconaPGCluster and PostgresCluster", func() { - status := cr.Status - Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) - cr.Status = status - Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) - - Eventually(func() error { - return k8sClient.Get(ctx, client.ObjectKeyFromObject(cr), new(v2.PerconaPGCluster)) - }, time.Second*15, time.Millisecond*250).Should(BeNil()) - - Eventually(func() error { - return k8sClient.Get(ctx, client.ObjectKeyFromObject(cr), new(v1beta1.PostgresCluster)) - }, time.Second*15, time.Millisecond*250).Should(BeNil()) - }) - - It("should wait until PostgresCluster will stop to Reconcile multiple times", func() { - Eventually(func() bool { - pgCluster := new(v1beta1.PostgresCluster) - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(cr), pgCluster) - if err != nil { - return false - } - // When ManagedFields get field with `status` subresource, crunchy's Reconcile stops being called - for _, f := range pgCluster.ManagedFields { - if f.Manager == postgrescluster.ControllerName && f.Subresource == "status" { - return true - } - } - - return false - }, time.Second*60, time.Millisecond*250).Should(Equal(true)) - reconcileCount = getReconcileCount(crunchyR) - }) - }) - - var secret *corev1.Secret - Context("Create secret", func() { - secret = &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "some-secret", - Namespace: ns, - Labels: map[string]string{ - naming.LabelCluster: cr.Name, - }, - }, - Data: map[string][]byte{ - "some-data": []byte("data"), - }, - } - It("should create secret", func() { - Expect(k8sClient.Create(ctx, secret)).To(Succeed()) - Eventually(func() error { - return k8sClient.Get(ctx, client.ObjectKeyFromObject(secret), new(corev1.Secret)) - }, time.Second*15, time.Millisecond*250).Should(BeNil()) - }) - - It("should reconcile 0 times", func() { - Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*15, time.Millisecond*250). - Should(Equal(reconcileCount)) - }) - }) - - Context("Update secret data", func() { - It("should update secret data", func() { - secret.Data["some-data"] = []byte("updated-data") - Expect(k8sClient.Update(ctx, secret)).To(Succeed()) - }) - - It("should wait until secret is updated", func() { - Eventually(func() bool { - newSecret := new(corev1.Secret) - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(secret), newSecret) - if err != nil { - return false - } - return string(newSecret.Data["some-data"]) == "updated-data" - }, time.Second*15, time.Millisecond*250).Should(BeTrue()) - }) - - It("should reconcile 1 time", func() { - Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*20, time.Millisecond*250). - Should(Equal(reconcileCount + 1)) - }) - - It("should update secret data", func() { - secret.Data["some-data"] = []byte("updated-data-2") - Expect(k8sClient.Update(ctx, secret)).To(Succeed()) - }) - - It("should wait until secret is updated", func() { - Eventually(func() bool { - newSecret := new(corev1.Secret) - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(secret), newSecret) - if err != nil { - return false - } - return string(newSecret.Data["some-data"]) == "updated-data-2" - }, time.Second*15, time.Millisecond*250).Should(BeTrue()) - }) - - It("should reconcile 2 times", func() { - Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*20, time.Millisecond*250). - Should(Equal(reconcileCount + 2)) - }) - }) - - Context("Update secret data and remove labels", func() { - It("should remove cluster label and update data", func() { - secret.Labels = make(map[string]string) - secret.Data["some-data"] = []byte("updated-data-3") - Expect(k8sClient.Update(ctx, secret)).To(Succeed()) - }) - - It("should wait until secret is updated", func() { - Eventually(func() bool { - newSecret := new(corev1.Secret) - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(secret), newSecret) - if err != nil { - return false - } - return string(newSecret.Data["some-data"]) == "updated-data-3" - }, time.Second*15, time.Millisecond*250).Should(BeTrue()) - }) - - It("should reconcile 2 times", func() { - Eventually(func() int { return getReconcileCount(crunchyR) }, time.Second*15, time.Millisecond*250). - Should(Equal(reconcileCount + 2)) - }) - }) -}) - var _ = Describe("Users", Ordered, func() { ctx := context.Background() From c77a6b2b457559d6dbb1deef06abd3fc277170d9 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Sat, 28 Jun 2025 21:05:13 +0300 Subject: [PATCH 046/300] K8SPG-613: fix cr.yaml (#1185) https://perconadev.atlassian.net/browse/K8SPG-613 Co-authored-by: Viacheslav Sarzhan --- deploy/cr.yaml | 81 ++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 638faec75b..7f22bfe97f 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -17,24 +17,25 @@ spec: # cpu: 2.0 # memory: 4Gi # containerSecurityContext: -# fsGroup: 1001 # runAsUser: 1001 -# runAsNonRoot: true -# fsGroupChangePolicy: "OnRootMismatch" # runAsGroup: 1001 -# seLinuxOptions: -# type: spc_t -# level: s0:c123,c456 +# runAsNonRoot: true +# privileged: false +# allowPrivilegeEscalation: false +# readOnlyRootFilesystem: true +# capabilities: +# add: +# - NET_ADMIN +# - SYS_TIME +# drop: +# - ALL # seccompProfile: # type: Localhost # localhostProfile: localhost/profile.json -# supplementalGroups: -# - 1001 -# sysctls: -# - name: net.ipv4.tcp_keepalive_time -# value: "600" -# - name: net.ipv4.tcp_keepalive_intvl -# value: "60" +# procMount: Default +# seLinuxOptions: +# type: spc_t +# level: s0:c123,c456 # metadata: # annotations: # example-annotation: value @@ -182,24 +183,25 @@ spec: # cpu: 2.0 # memory: 4Gi # containerSecurityContext: -# fsGroup: 1001 # runAsUser: 1001 -# runAsNonRoot: true -# fsGroupChangePolicy: "OnRootMismatch" # runAsGroup: 1001 -# seLinuxOptions: -# type: spc_t -# level: s0:c123,c456 +# runAsNonRoot: true +# privileged: false +# allowPrivilegeEscalation: false +# readOnlyRootFilesystem: true +# capabilities: +# add: +# - NET_ADMIN +# - SYS_TIME +# drop: +# - ALL # seccompProfile: # type: Localhost # localhostProfile: localhost/profile.json -# supplementalGroups: -# - 1001 -# sysctls: -# - name: net.ipv4.tcp_keepalive_time -# value: "600" -# - name: net.ipv4.tcp_keepalive_intvl -# value: "60" +# procMount: Default +# seLinuxOptions: +# type: spc_t +# level: s0:c123,c456 affinity: podAntiAffinity: @@ -385,24 +387,25 @@ spec: # cpu: 2.0 # memory: 4Gi # containerSecurityContext: -# fsGroup: 1001 # runAsUser: 1001 -# runAsNonRoot: true -# fsGroupChangePolicy: "OnRootMismatch" # runAsGroup: 1001 -# seLinuxOptions: -# type: spc_t -# level: s0:c123,c456 +# runAsNonRoot: true +# privileged: false +# allowPrivilegeEscalation: false +# readOnlyRootFilesystem: true +# capabilities: +# add: +# - NET_ADMIN +# - SYS_TIME +# drop: +# - ALL # seccompProfile: # type: Localhost # localhostProfile: localhost/profile.json -# supplementalGroups: -# - 1001 -# sysctls: -# - name: net.ipv4.tcp_keepalive_time -# value: "600" -# - name: net.ipv4.tcp_keepalive_intvl -# value: "60" +# procMount: Default +# seLinuxOptions: +# type: spc_t +# level: s0:c123,c456 # containers: # pgbackrest: # resources: From c0aaf3ddea77ec46bbde93e305f861932c18065a Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Sat, 28 Jun 2025 21:05:39 +0300 Subject: [PATCH 047/300] K8SPG-799 configure imagepullsecrets for patroni version check pod - add envtests (#1184) * K8SPG-799 configure imagepullsecrets for patroni version check pod - add envtests * fix imports * remove resources assertion - ideally whole pod should be extracted from here * fix comments * use right image --------- Co-authored-by: Viacheslav Sarzhan --- percona/controller/pgcluster/controller.go | 1 + .../controller/pgcluster/controller_test.go | 181 ++++++++++++++++++ 2 files changed, 182 insertions(+) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index c52e5b8625..128e682c75 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -436,6 +436,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, }, SecurityContext: cr.Spec.InstanceSets[0].SecurityContext, TerminationGracePeriodSeconds: ptr.To(int64(5)), + ImagePullSecrets: cr.Spec.ImagePullSecrets, Resources: &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("100m"), diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 3d91d4edb2..5a32bc090d 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -21,6 +21,7 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -1517,6 +1518,186 @@ var _ = Describe("ServiceAccount early creation", Ordered, func() { }) }) +var _ = Describe("patroni version check", Ordered, func() { + ctx := context.Background() + + const crName = "patroni-version-test" + const ns = crName + crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName, + Namespace: ns, + }, + } + + BeforeAll(func() { + By("Creating the Namespace to perform the tests") + err := k8sClient.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the Namespace to perform the tests") + _ = k8sClient.Delete(ctx, namespace) + }) + + Context("With custom patroni version annotation", func() { + cr, err := readDefaultCR(crName, ns) + It("should read default cr.yaml", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + It("should create PerconaPGCluster with custom patroni version", func() { + if cr.Annotations == nil { + cr.Annotations = make(map[string]string) + } + cr.Annotations[pNaming.AnnotationCustomPatroniVersion] = "3.2.1" + + status := cr.Status + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + cr.Status = status + Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) + }) + + It("should successfully reconcile patroni version check", func() { + reconcilerInstance := reconciler(cr) + err := reconcilerInstance.reconcilePatroniVersionCheck(ctx, cr) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should copy custom patroni version to status", func() { + updatedCR := &v2.PerconaPGCluster{} + Expect(k8sClient.Get(ctx, crNamespacedName, updatedCR)).Should(Succeed()) + + Expect(updatedCR.Status.PatroniVersion).To(Equal("3.2.1")) + }) + }) + + Context("Without custom patroni version annotation", func() { + const crName2 = "patroni-version-test-2" + const ns2 = crName2 + crNamespacedName2 := types.NamespacedName{Name: crName2, Namespace: ns2} + + namespace2 := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName2, + Namespace: ns2, + }, + } + + BeforeAll(func() { + By("Creating the second namespace") + err := k8sClient.Create(ctx, namespace2) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the second namespace") + _ = k8sClient.Delete(ctx, namespace2) + }) + + cr2, err := readDefaultCR(crName2, ns2) + It("should read default cr.yaml", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + It("should create PerconaPGCluster without custom patroni version annotation", func() { + if cr2.Annotations == nil { + cr2.Annotations = make(map[string]string) + } + delete(cr2.Annotations, pNaming.AnnotationCustomPatroniVersion) + + uid := int64(1001) + cr2.Spec.InstanceSets[0].SecurityContext = &corev1.PodSecurityContext{ + RunAsUser: &uid, + } + cr2.Spec.ImagePullSecrets = []corev1.LocalObjectReference{ + {Name: "test-pull-secret"}, + } + + cr2.Status.PatroniVersion = "3.1.0" + cr2.Status.Postgres.ImageID = "some-image-id" + + status := cr2.Status + Expect(k8sClient.Create(ctx, cr2)).Should(Succeed()) + cr2.Status = status + Expect(k8sClient.Status().Update(ctx, cr2)).Should(Succeed()) + + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: cr2.Name + "-instance-pod", + Namespace: cr2.Namespace, + Labels: map[string]string{ + "postgres-operator.crunchydata.com/cluster": cr2.Name, + "postgres-operator.crunchydata.com/instance": "instance", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "database", + Image: "postgres:16", + }, + }, + }, + } + Expect(k8sClient.Create(ctx, pod)).Should(Succeed()) + + pod.Status = corev1.PodStatus{ + Phase: corev1.PodRunning, + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "database", + ImageID: "postgres:16", + }, + }, + } + Expect(k8sClient.Status().Update(ctx, pod)).Should(Succeed()) + }) + + It("should create patroni version check pod and return errPatroniVersionCheckWait", func() { + reconcilerInstance := reconciler(cr2) + err := reconcilerInstance.reconcilePatroniVersionCheck(ctx, cr2) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("waiting for pod to initialize")) + }) + + It("should have created patroni version check pod with correct configuration", func() { + podName := cr2.Name + "-patroni-version-check" + pod := &corev1.Pod{} + err = k8sClient.Get(ctx, types.NamespacedName{Name: podName, Namespace: cr2.Namespace}, pod) + Expect(err).NotTo(HaveOccurred()) + + Expect(pod.Spec.Containers).To(HaveLen(1)) + Expect(pod.Spec.Containers[0].Name).To(Equal(pNaming.ContainerPatroniVersionCheck)) + Expect(pod.Spec.Containers[0].Image).To(Equal(cr2.Spec.Image)) + Expect(pod.Spec.Containers[0].Command).To(Equal([]string{"bash"})) + Expect(pod.Spec.Containers[0].Args).To(Equal([]string{"-c", "sleep 60"})) + + uid := int64(1001) + expectedSecurityContext := &corev1.PodSecurityContext{ + RunAsUser: &uid, + } + expectedImagePullSecrets := []corev1.LocalObjectReference{ + {Name: "test-pull-secret"}, + } + + Expect(pod.Spec.SecurityContext).To(Equal(expectedSecurityContext)) + Expect(pod.Spec.TerminationGracePeriodSeconds).To(Equal(ptr.To(int64(5)))) + Expect(pod.Spec.ImagePullSecrets).To(Equal(expectedImagePullSecrets)) + }) + + It("should preserve existing patroni version in annotation", func() { + updatedCR := &v2.PerconaPGCluster{} + Expect(k8sClient.Get(ctx, crNamespacedName2, updatedCR)).Should(Succeed()) + + Expect(updatedCR.Status.PatroniVersion).To(Equal("3.1.0")) + }) + }) +}) + var _ = Describe("CR Validations", Ordered, func() { ctx := context.Background() const crName = "cr-validation" From fbaf34e610b83f26aabed56596c68f6107482bd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 28 Jun 2025 21:06:23 +0300 Subject: [PATCH 048/300] CLOUD-727: Bump k8s.io/apiextensions-apiserver from 0.32.3 to 0.33.2 (#1174) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.32.3 to 0.33.2. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.32.3...v0.33.2) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.33.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 789360638d..32f54dc28b 100644 --- a/go.mod +++ b/go.mod @@ -34,10 +34,10 @@ require ( golang.org/x/crypto v0.38.0 google.golang.org/grpc v1.73.0 gotest.tools/v3 v3.5.2 - k8s.io/api v0.33.0 + k8s.io/api v0.33.2 k8s.io/apimachinery v0.33.2 - k8s.io/client-go v0.33.0 - k8s.io/component-base v0.33.0 + k8s.io/client-go v0.33.2 + k8s.io/component-base v0.33.2 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.4.0 ) @@ -128,7 +128,7 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.33.0 + k8s.io/apiextensions-apiserver v0.33.2 k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 diff --git a/go.sum b/go.sum index fb8145441d..57ddc695f1 100644 --- a/go.sum +++ b/go.sum @@ -396,16 +396,16 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU= -k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM= -k8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs= -k8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc= +k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY= +k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs= +k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8= +k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8= k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98= -k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg= -k8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk= -k8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU= +k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E= +k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo= +k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0= +k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= From 923b32bd1680656e2fec2bdced2d46026804d592 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 28 Jun 2025 21:21:22 +0300 Subject: [PATCH 049/300] CLOUD-727: Bump go.nhat.io/grpcmock from 0.30.0 to 0.31.0 (#1178) Bumps [go.nhat.io/grpcmock](https://github.com/nhatthm/grpcmock) from 0.30.0 to 0.31.0. - [Release notes](https://github.com/nhatthm/grpcmock/releases) - [Commits](https://github.com/nhatthm/grpcmock/compare/v0.30.0...v0.31.0) --- updated-dependencies: - dependency-name: go.nhat.io/grpcmock dependency-version: 0.31.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 +++--- go.sum | 80 ++++++---------------------------------------------------- 2 files changed, 12 insertions(+), 76 deletions(-) diff --git a/go.mod b/go.mod index 32f54dc28b..ddee8a05bc 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 - go.nhat.io/grpcmock v0.30.0 + go.nhat.io/grpcmock v0.31.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 go.opentelemetry.io/otel v1.36.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 @@ -44,11 +44,12 @@ require ( require ( github.com/evanphx/json-patch/v5 v5.9.11 // indirect - github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/btree v1.1.3 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect @@ -81,7 +82,6 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -124,7 +124,7 @@ require ( golang.org/x/tools v0.33.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 57ddc695f1..483a1533bc 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc h1:aBpUepmWt8NsLH0fOA6vb8CCvIIJ4jMNxpvR36PaRSs= github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc/go.mod h1:dOzRkbUNd/qpn35nOSy60ZQBiP9wa9g1kh9kaMg/tOk= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -8,7 +6,6 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -19,33 +16,24 @@ github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= -github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -73,18 +61,12 @@ github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZ github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= @@ -92,7 +74,6 @@ github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -106,8 +87,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= @@ -126,7 +107,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -167,12 +147,10 @@ github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -182,7 +160,6 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4 github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= @@ -195,7 +172,6 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= @@ -203,10 +179,8 @@ github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -231,8 +205,8 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.nhat.io/aferomock v0.8.0 h1:jESv25NuTpA/Wga+AOKqKI1lPKdYiBYvxpIUDJWyfPM= go.nhat.io/aferomock v0.8.0/go.mod h1:thJD/9Yeo+CcIW45u6rNU8WYc1yIWdqfOSpKcGtjAXw= -go.nhat.io/grpcmock v0.30.0 h1:n6LRUTACW6LMj3+U3XTdLqRSbE/qxWlL1Z6wF/FS6jk= -go.nhat.io/grpcmock v0.30.0/go.mod h1:UivGqlV49ExKl3ceD35f2bH6UBs5zfEcYQMkBHqnIfA= +go.nhat.io/grpcmock v0.31.0 h1:UK7xeS0qGY/duLnKMvCb3JtR9fy9GQ2/MbEsrFvkXIE= +go.nhat.io/grpcmock v0.31.0/go.mod h1:BuY58zdX1LWnC4kkjvkK+fpIC69P4lNQMjL/6++KaD4= go.nhat.io/matcher/v2 v2.0.0 h1:W+rbHi0hKuZHtOQH4U5g+KwyKyfVioIxrxjoGRcUETE= go.nhat.io/matcher/v2 v2.0.0/go.mod h1:cL5oYp0M9A4L8jEGqjmUfy+k7AXVDddoVt6aYIL1r5g= go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= @@ -259,16 +233,12 @@ go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKr go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -277,20 +247,11 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -299,25 +260,19 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -336,11 +291,6 @@ golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -353,20 +303,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 h1:TwXJCGVREgQ/cl18iY0Z4wJCTL/GmW+Um2oSwZiZPnc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= @@ -374,7 +314,6 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -389,13 +328,10 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY= k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs= k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8= From 97d93c3dfec706d660379e23dbf181700519b92b Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Sun, 29 Jun 2025 13:22:22 +0300 Subject: [PATCH 050/300] K8SPG-729: add version label to perconapgupgrades crd (#1171) https://perconadev.atlassian.net/browse/K8SPG-729 Co-authored-by: Viacheslav Sarzhan --- config/crd/kustomization.yaml | 1 + config/crd/patches/versionlabel_in_perconapgupgrade.yaml | 6 ++++++ deploy/bundle.yaml | 2 ++ deploy/crd.yaml | 2 ++ deploy/cw-bundle.yaml | 2 ++ percona/version/version.go | 1 + percona/version/version_test.go | 1 + 7 files changed, 15 insertions(+) create mode 100644 config/crd/patches/versionlabel_in_perconapgupgrade.yaml diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 511e52180e..58ff2bc5bc 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -12,3 +12,4 @@ patchesStrategicMerge: - patches/versionlabel_in_perconapgclusters.yaml - patches/versionlabel_in_perconapgbackups.yaml - patches/versionlabel_in_perconapgrestores.yaml +- patches/versionlabel_in_perconapgupgrade.yaml diff --git a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml new file mode 100644 index 0000000000..4f41858170 --- /dev/null +++ b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml @@ -0,0 +1,6 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgupgrades.pgv2.percona.com + labels: + pgv2.percona.com/version: v2.7.0 diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index b23cab131a..038c2b40ff 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -19204,6 +19204,8 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 + labels: + pgv2.percona.com/version: v2.7.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 19de1e5f34..d79c211c89 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -19204,6 +19204,8 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 + labels: + pgv2.percona.com/version: v2.7.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 2c3b64903b..8f3313a07e 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -19204,6 +19204,8 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 + labels: + pgv2.percona.com/version: v2.7.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/percona/version/version.go b/percona/version/version.go index 956f4a557c..85f61bc83d 100644 --- a/percona/version/version.go +++ b/percona/version/version.go @@ -19,6 +19,7 @@ import ( //go:generate sh -c "yq -i '.metadata.labels.\"pgv2.percona.com/version\" = \"v\" + load(\"version.txt\")' ../../config/crd/patches/versionlabel_in_perconapgclusters.yaml" //go:generate sh -c "yq -i '.metadata.labels.\"pgv2.percona.com/version\" = \"v\" + load(\"version.txt\")' ../../config/crd/patches/versionlabel_in_perconapgbackups.yaml" //go:generate sh -c "yq -i '.metadata.labels.\"pgv2.percona.com/version\" = \"v\" + load(\"version.txt\")' ../../config/crd/patches/versionlabel_in_perconapgrestores.yaml" +//go:generate sh -c "yq -i '.metadata.labels.\"pgv2.percona.com/version\" = \"v\" + load(\"version.txt\")' ../../config/crd/patches/versionlabel_in_perconapgupgrade.yaml" //go:embed version.txt var version string diff --git a/percona/version/version_test.go b/percona/version/version_test.go index f128766821..6ee19eb059 100644 --- a/percona/version/version_test.go +++ b/percona/version/version_test.go @@ -20,6 +20,7 @@ func TestCRDVersionLabel(t *testing.T) { "perconapgbackups.pgv2.percona.com", "perconapgclusters.pgv2.percona.com", "perconapgrestores.pgv2.percona.com", + "perconapgupgrades.pgv2.percona.com", } _, filename, _, ok := runtime.Caller(0) From ebe981f4cffbb44fd7115dd183a2a0e26b088176 Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Sun, 29 Jun 2025 07:23:25 -0300 Subject: [PATCH 051/300] CLOUD-915: Add flags to disable monitoring and logging in PR job (#1187) * CLOUD-915: Add flags to disable monitoring and logging in PR job * Add total test time and some refactor * Revert some vars --------- Co-authored-by: Viacheslav Sarzhan --- Jenkinsfile | 77 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6e6282fa79..8ddb00a476 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,25 +1,40 @@ -region="us-central1-a" -testUrlPrefix="https://percona-jenkins-artifactory-public.s3.amazonaws.com/cloud-pg-operator" -tests=[] +region = 'us-central1-a' +testUrlPrefix = "https://percona-jenkins-artifactory-public.s3.amazonaws.com/cloud-pg-operator" +tests = [] void createCluster(String CLUSTER_SUFFIX) { withCredentials([string(credentialsId: 'GCP_PROJECT_ID', variable: 'GCP_PROJECT'), file(credentialsId: 'gcloud-key-file', variable: 'CLIENT_SECRET_FILE')]) { sh """ - NODES_NUM=3 export KUBECONFIG=/tmp/$CLUSTER_NAME-${CLUSTER_SUFFIX} + gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE + gcloud config set project $GCP_PROJECT ret_num=0 while [ \${ret_num} -lt 15 ]; do ret_val=0 - gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE - gcloud config set project $GCP_PROJECT - gcloud container clusters list --filter $CLUSTER_NAME-${CLUSTER_SUFFIX} --zone $region --format='csv[no-heading](name)' | xargs gcloud container clusters delete --zone $region --quiet || true - gcloud container clusters create --zone $region $CLUSTER_NAME-${CLUSTER_SUFFIX} --cluster-version=1.30 --machine-type=n1-standard-4 --preemptible --disk-size 30 --num-nodes=\$NODES_NUM --network=jenkins-vpc --subnetwork=jenkins-${CLUSTER_SUFFIX} --no-enable-autoupgrade --cluster-ipv4-cidr=/21 --labels delete-cluster-after-hours=6 --enable-ip-alias && \ + gcloud container clusters list --filter $CLUSTER_NAME-${CLUSTER_SUFFIX} --zone ${region} --format='csv[no-heading](name)' | xargs gcloud container clusters delete --zone ${region} --quiet || true + gcloud container clusters create $CLUSTER_NAME-${CLUSTER_SUFFIX} \ + --preemptible \ + --zone=${region} \ + --machine-type='n1-standard-4' \ + --cluster-version='1.30' \ + --num-nodes=3 \ + --labels='delete-cluster-after-hours=6' \ + --disk-size=30 \ + --network=jenkins-vpc \ + --subnetwork=jenkins-${CLUSTER_SUFFIX} \ + --cluster-ipv4-cidr=/21 \ + --enable-ip-alias \ + --no-enable-autoupgrade \ + --monitoring=NONE \ + --logging=NONE \ + --no-enable-managed-prometheus \ + --quiet && \ kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user jenkins@"$GCP_PROJECT".iam.gserviceaccount.com || ret_val=\$? if [ \${ret_val} -eq 0 ]; then break; fi ret_num=\$((ret_num + 1)) done if [ \${ret_num} -eq 15 ]; then - gcloud container clusters list --filter $CLUSTER_NAME-${CLUSTER_SUFFIX} --zone $region --format='csv[no-heading](name)' | xargs gcloud container clusters delete --zone $region --quiet || true + gcloud container clusters list --filter $CLUSTER_NAME-${CLUSTER_SUFFIX} --zone ${region} --format='csv[no-heading](name)' | xargs gcloud container clusters delete --zone ${region} --quiet || true exit 1 fi """ @@ -41,7 +56,7 @@ void shutdownCluster(String CLUSTER_SUFFIX) { kubectl delete pods --all -n \$namespace --force --grace-period=0 || true done kubectl get svc --all-namespaces || true - gcloud container clusters delete --zone $region $CLUSTER_NAME-${CLUSTER_SUFFIX} + gcloud container clusters delete --zone ${region} $CLUSTER_NAME-${CLUSTER_SUFFIX} """ } } @@ -65,7 +80,7 @@ void deleteOldClusters(String FILTER) { break fi done - gcloud container clusters delete --async --zone $region --quiet \$GKE_CLUSTER || true + gcloud container clusters delete --async --zone ${region} --quiet \$GKE_CLUSTER || true done fi """ @@ -120,7 +135,7 @@ void markPassedTests() { for (int i=0; i/dev/null 2>&1", returnStatus: true) if (retFileExists == 0) { @@ -149,12 +164,30 @@ void printKubernetesStatus(String LOCATION, String CLUSTER_SUFFIX) { """ } -TestsReport = '| Test name | Status |\r\n| ------------- | ------------- |' +String formatTime(def time) { + if (!time || time == "N/A") return "N/A" + + try { + def totalSeconds = time as Double + def hours = (totalSeconds / 3600) as Integer + def minutes = ((totalSeconds % 3600) / 60) as Integer + def seconds = (totalSeconds % 60) as Integer + + return String.format("%02d:%02d:%02d", hours, minutes, seconds) + + } catch (Exception e) { + println("Error converting time: ${e.message}") + return time.toString() + } +} + +TestsReport = '| Test Name | Result | Time |\r\n| ----------- | -------- | ------ |' TestsReportXML = '\n' void makeReport() { - def wholeTestAmount=tests.size() + def wholeTestAmount = tests.size() def startedTestAmount = 0 + def totalTestTime = 0 for (int i=0; i<'+ testResult +'/>\n' } - TestsReport = TestsReport + "\r\n| We run $startedTestAmount out of $wholeTestAmount|" + TestsReport = TestsReport + "\r\n| We run $startedTestAmount out of $wholeTestAmount | | " + formatTime(totalTestTime) + " |" TestsReportXML = TestsReportXML + '\n' sh """ @@ -244,10 +281,10 @@ void runTest(Integer TEST_ID) { void prepareNode() { sh """ - sudo curl -s -L -o /usr/local/bin/kubectl https://dl.k8s.io/release/\$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl && sudo chmod +x /usr/local/bin/kubectl + sudo curl -sLo /usr/local/bin/kubectl https://dl.k8s.io/release/\$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl && sudo chmod +x /usr/local/bin/kubectl kubectl version --client --output=yaml - curl -fsSL https://get.helm.sh/helm-v3.12.3-linux-amd64.tar.gz | sudo tar -C /usr/local/bin --strip-components 1 -xzf - linux-amd64/helm + curl -fsSL https://get.helm.sh/helm-v3.18.3-linux-amd64.tar.gz | sudo tar -C /usr/local/bin --strip-components 1 -xzf - linux-amd64/helm sudo curl -fsSL https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -o /usr/local/bin/yq && sudo chmod +x /usr/local/bin/yq sudo curl -fsSL https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux64 -o /usr/local/bin/jq && sudo chmod +x /usr/local/bin/jq @@ -258,8 +295,8 @@ void prepareNode() { kubectl krew install assert - # v0.17.0 kuttl version - kubectl krew install --manifest-url https://raw.githubusercontent.com/kubernetes-sigs/krew-index/336ef83542fd2f783bfa2c075b24599e834dcc77/plugins/kuttl.yaml + # v0.22.0 kuttl version + kubectl krew install --manifest-url https://raw.githubusercontent.com/kubernetes-sigs/krew-index/02d5befb2bc9554fdcd8386b8bfbed2732d6802e/plugins/kuttl.yaml echo \$(kubectl kuttl --version) is installed sudo tee /etc/yum.repos.d/google-cloud-sdk.repo << EOF From 0232e2848003588b8d058a0b5165d94b94e05816 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Jun 2025 13:23:48 +0300 Subject: [PATCH 052/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace (#1156) Bumps [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) from 1.35.0 to 1.36.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.35.0...v1.36.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index ddee8a05bc..311b7d28ff 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.24.1 require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc - github.com/go-logr/logr v1.4.2 + github.com/go-logr/logr v1.4.3 github.com/go-openapi/errors v0.22.1 github.com/go-openapi/runtime v0.28.0 github.com/go-openapi/strfmt v0.23.0 @@ -24,12 +24,12 @@ require ( github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.31.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 - go.opentelemetry.io/otel v1.36.0 + go.opentelemetry.io/otel v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 - go.opentelemetry.io/otel/sdk v1.36.0 - go.opentelemetry.io/otel/trace v1.36.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 + go.opentelemetry.io/otel/sdk v1.37.0 + go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.38.0 google.golang.org/grpc v1.73.0 @@ -111,7 +111,7 @@ require ( go.mongodb.org/mongo-driver v1.14.0 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect - go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.40.0 // indirect diff --git a/go.sum b/go.sum index 483a1533bc..67ba6e9a9f 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8 github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -215,22 +215,22 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= -go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= -go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= -go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= -go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= -go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= -go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= From 5bd96b424ce265bf5d3f11d93d996efb91de512c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Mon, 30 Jun 2025 09:50:52 +0300 Subject: [PATCH 053/300] Revert "K8SPG-737: expose `/pgdata` mountpoint for node_exporter (#1113)" (#1188) --- .../08-check-mountpoint-expose.yaml | 20 ------------- .../08-check-mountpoint-expose.yaml | 20 ------------- ... => 08-deleted-from-server-inventory.yaml} | 0 .../controller/postgrescluster/instance.go | 3 -- percona/pmm/pmm.go | 30 +++++-------------- percona/pmm/pmm_test.go | 6 ++-- 6 files changed, 11 insertions(+), 68 deletions(-) delete mode 100644 e2e-tests/tests/monitoring-pmm3/08-check-mountpoint-expose.yaml delete mode 100644 e2e-tests/tests/monitoring/08-check-mountpoint-expose.yaml rename e2e-tests/tests/monitoring/{09-deleted-from-server-inventory.yaml => 08-deleted-from-server-inventory.yaml} (100%) diff --git a/e2e-tests/tests/monitoring-pmm3/08-check-mountpoint-expose.yaml b/e2e-tests/tests/monitoring-pmm3/08-check-mountpoint-expose.yaml deleted file mode 100644 index 2ebf03a182..0000000000 --- a/e2e-tests/tests/monitoring-pmm3/08-check-mountpoint-expose.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - series_fetched=$(curl --insecure -G "https://admin:admin@$(get_service_ip monitoring-service)/prometheus/api/v1/query_range" \ - --data-urlencode "query=node_filesystem_free_bytes{mountpoint=\"/pgdata\"}" \ - --data-urlencode "start=$(($(date +%s) - 300))" \ - --data-urlencode "end=$(date +%s)" \ - --data-urlencode "step=5s" | jq -r '.stats.seriesFetched') - - if [[ $series_fetched == 0 ]]; then - echo "seriesFetched is 0" - exit 1 - fi - timeout: 360 diff --git a/e2e-tests/tests/monitoring/08-check-mountpoint-expose.yaml b/e2e-tests/tests/monitoring/08-check-mountpoint-expose.yaml deleted file mode 100644 index 2ebf03a182..0000000000 --- a/e2e-tests/tests/monitoring/08-check-mountpoint-expose.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - series_fetched=$(curl --insecure -G "https://admin:admin@$(get_service_ip monitoring-service)/prometheus/api/v1/query_range" \ - --data-urlencode "query=node_filesystem_free_bytes{mountpoint=\"/pgdata\"}" \ - --data-urlencode "start=$(($(date +%s) - 300))" \ - --data-urlencode "end=$(date +%s)" \ - --data-urlencode "step=5s" | jq -r '.stats.seriesFetched') - - if [[ $series_fetched == 0 ]]; then - echo "seriesFetched is 0" - exit 1 - fi - timeout: 360 diff --git a/e2e-tests/tests/monitoring/09-deleted-from-server-inventory.yaml b/e2e-tests/tests/monitoring/08-deleted-from-server-inventory.yaml similarity index 100% rename from e2e-tests/tests/monitoring/09-deleted-from-server-inventory.yaml rename to e2e-tests/tests/monitoring/08-deleted-from-server-inventory.yaml diff --git a/internal/controller/postgrescluster/instance.go b/internal/controller/postgrescluster/instance.go index b1e3cc39be..079b1d2e4f 100644 --- a/internal/controller/postgrescluster/instance.go +++ b/internal/controller/postgrescluster/instance.go @@ -1365,9 +1365,6 @@ func generateInstanceStatefulSetIntent(_ context.Context, // containers see each other's processes. // - https://docs.k8s.io/tasks/configure-pod-container/share-process-namespace/ sts.Spec.Template.Spec.ShareProcessNamespace = initialize.Bool(true) - if cluster.CompareVersion("2.7.0") >= 0 { - sts.Spec.Template.Spec.ShareProcessNamespace = initialize.Bool(false) // K8SPG-737: should be false - } // Patroni calls the Kubernetes API and pgBackRest may interact with a cloud // storage provider. Use the instance ServiceAccount and automatically mount diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index 0a5e144489..7308ce98ea 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -7,7 +7,6 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/postgres" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" ) @@ -43,21 +42,6 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { pmmSpec := pgc.Spec.PMM - volumeMounts := []corev1.VolumeMount{ - { - Name: "cert-volume", - MountPath: "/pgconf/tls", - ReadOnly: true, - }, - } - if pgc.CompareVersion("2.7.0") >= 0 { - volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: postgres.DataVolumeMount().Name, - MountPath: postgres.DataVolumeMount().MountPath, - ReadOnly: true, - }) - } - return corev1.Container{ Name: "pmm-client", Image: pmmSpec.Image, @@ -90,7 +74,13 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { }, }, }, - VolumeMounts: volumeMounts, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "cert-volume", + MountPath: "/pgconf/tls", + ReadOnly: true, + }, + }, Env: []corev1.EnvVar{ { Name: "POD_NAME", @@ -293,13 +283,7 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { MountPath: "/pgconf/tls", ReadOnly: true, }, - { - Name: postgres.DataVolumeMount().Name, - MountPath: postgres.DataVolumeMount().MountPath, - ReadOnly: true, - }, }, - Env: []corev1.EnvVar{ { Name: "POD_NAME", diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index 47b3b6b907..482dfa4f59 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -135,6 +136,7 @@ func TestContainer(t *testing.T) { assert.Contains(t, container.Env, tt.verificationEnvVar()) }) } + } func TestSidecarContainerV2(t *testing.T) { @@ -244,7 +246,7 @@ func TestSidecarContainerV2(t *testing.T) { } } - assert.Len(t, container.VolumeMounts, 2) + assert.Len(t, container.VolumeMounts, 1) assert.Equal(t, "/pgconf/tls", container.VolumeMounts[0].MountPath) assert.True(t, container.VolumeMounts[0].ReadOnly) } @@ -351,7 +353,7 @@ func TestSidecarContainerV3(t *testing.T) { } } - assert.Len(t, container.VolumeMounts, 2) + assert.Len(t, container.VolumeMounts, 1) assert.Equal(t, "/pgconf/tls", container.VolumeMounts[0].MountPath) assert.True(t, container.VolumeMounts[0].ReadOnly) } From afa6df96c89ac1361f21e344f4747557136475e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 09:52:33 +0300 Subject: [PATCH 054/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace (#1159) Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace](https://github.com/open-telemetry/opentelemetry-go) from 1.35.0 to 1.36.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.35.0...v1.36.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace dependency-version: 1.36.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 311b7d28ff..a3df5c325d 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( go.nhat.io/grpcmock v0.31.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 go.opentelemetry.io/otel v1.37.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 go.opentelemetry.io/otel/sdk v1.37.0 @@ -112,7 +112,7 @@ require ( go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect go.opentelemetry.io/otel/metric v1.37.0 // indirect - go.opentelemetry.io/proto/otlp v1.5.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.40.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect @@ -123,8 +123,8 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.33.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 67ba6e9a9f..9c9af451ef 100644 --- a/go.sum +++ b/go.sum @@ -217,8 +217,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRND go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI= @@ -231,8 +231,8 @@ go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5J go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -303,10 +303,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM= -google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= From 5f89de781e2511c0afaba63d76d3c479c11eef9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 09:52:58 +0300 Subject: [PATCH 055/300] CLOUD-727: Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#1157) Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.60.0 to 0.61.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.60.0...zpages/v0.61.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp dependency-version: 0.61.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index a3df5c325d..370f6003b9 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.31.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 go.opentelemetry.io/otel v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 diff --git a/go.sum b/go.sum index 9c9af451ef..e9a6216308 100644 --- a/go.sum +++ b/go.sum @@ -213,8 +213,8 @@ go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= go.nhat.io/wait v0.1.0/go.mod h1:+ijMghc9/9zXi+HDcs49HNReprvXOZha2Q3jTOtqJrE= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= @@ -227,8 +227,8 @@ go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/Wgbsd go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= From 99b7ea45d43a1686a120f5cb5bc3849618d0d670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 10:04:21 +0300 Subject: [PATCH 056/300] CLOUD-727: Bump golangci/golangci-lint-action from 7 to 8 (#1164) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 7 to 8. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v7...v8) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: George Kechagias Co-authored-by: Viacheslav Sarzhan --- .github/workflows/reviewdog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 797e71d4f2..6a3caaa223 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -10,7 +10,7 @@ jobs: go-version: '^1.23' - uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v7 + uses: golangci/golangci-lint-action@v8 with: version: latest only-new-issues: true From c502fea364792d6391aebc8a02b5fc82b908487d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Mon, 30 Jun 2025 12:54:33 +0300 Subject: [PATCH 057/300] K8SPG-761: Apply PGO_WORKERS to all controllers (#1189) * K8SPG-761: Apply PGO_WORKERS to all controllers * fix unit tests * fix golangci-lint --------- Co-authored-by: Viacheslav Sarzhan --- cmd/postgres-operator/main.go | 12 ++++++++++-- cmd/postgres-operator/main_test.go | 22 ++++++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 197a8aabe3..73a718f6f4 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -305,12 +305,20 @@ func initManager(ctx context.Context) (runtime.Options, error) { } options.Controller.GroupKindConcurrency = map[string]int{ - "PostgresCluster." + v1beta1.GroupVersion.Group: 2, + "PostgresCluster." + v1beta1.GroupVersion.Group: 1, + "PGUpgrade." + v1beta1.GroupVersion.Group: 1, + "PGAdmin." + v1beta1.GroupVersion.Group: 1, + "PerconaPGCluster." + v2.GroupVersion.Group: 1, + "PerconaPGUpgrade." + v2.GroupVersion.Group: 1, + "PerconaPGBackup." + v2.GroupVersion.Group: 1, + "PerconaPGRestore." + v2.GroupVersion.Group: 1, } if s := os.Getenv("PGO_WORKERS"); s != "" { if i, err := strconv.Atoi(s); err == nil && i > 0 { - options.Controller.GroupKindConcurrency["PostgresCluster."+v1beta1.GroupVersion.Group] = i + for kind := range options.Controller.GroupKindConcurrency { + options.Controller.GroupKindConcurrency[kind] = i + } } else { log.Error(err, "PGO_WORKERS must be a positive number") } diff --git a/cmd/postgres-operator/main_test.go b/cmd/postgres-operator/main_test.go index 9235b7d2c2..d9865d56cd 100644 --- a/cmd/postgres-operator/main_test.go +++ b/cmd/postgres-operator/main_test.go @@ -28,7 +28,13 @@ func TestInitManager(t *testing.T) { assert.DeepEqual(t, options.Controller.GroupKindConcurrency, map[string]int{ - "PostgresCluster.postgres-operator.crunchydata.com": 2, + "PGAdmin.postgres-operator.crunchydata.com": 1, + "PGUpgrade.postgres-operator.crunchydata.com": 1, + "PerconaPGBackup.pgv2.percona.com": 1, + "PerconaPGCluster.pgv2.percona.com": 1, + "PerconaPGRestore.pgv2.percona.com": 1, + "PerconaPGUpgrade.pgv2.percona.com": 1, + "PostgresCluster.postgres-operator.crunchydata.com": 1, }) assert.Assert(t, options.Cache.DefaultNamespaces == nil) @@ -103,7 +109,13 @@ func TestInitManager(t *testing.T) { assert.NilError(t, err) assert.DeepEqual(t, options.Controller.GroupKindConcurrency, map[string]int{ - "PostgresCluster.postgres-operator.crunchydata.com": 2, + "PGAdmin.postgres-operator.crunchydata.com": 1, + "PGUpgrade.postgres-operator.crunchydata.com": 1, + "PerconaPGBackup.pgv2.percona.com": 1, + "PerconaPGCluster.pgv2.percona.com": 1, + "PerconaPGRestore.pgv2.percona.com": 1, + "PerconaPGUpgrade.pgv2.percona.com": 1, + "PostgresCluster.postgres-operator.crunchydata.com": 1, }) } }) @@ -115,6 +127,12 @@ func TestInitManager(t *testing.T) { assert.NilError(t, err) assert.DeepEqual(t, options.Controller.GroupKindConcurrency, map[string]int{ + "PGAdmin.postgres-operator.crunchydata.com": 19, + "PGUpgrade.postgres-operator.crunchydata.com": 19, + "PerconaPGBackup.pgv2.percona.com": 19, + "PerconaPGCluster.pgv2.percona.com": 19, + "PerconaPGRestore.pgv2.percona.com": 19, + "PerconaPGUpgrade.pgv2.percona.com": 19, "PostgresCluster.postgres-operator.crunchydata.com": 19, }) }) From da4126145a2bb78a590e5846a82dcfd1e28832be Mon Sep 17 00:00:00 2001 From: Jakub Jaruszewski Date: Mon, 30 Jun 2025 17:47:38 +0200 Subject: [PATCH 058/300] K8SPG-792 Make patroni check check respect default image settings (#1167) * K8SPG-792 Make patroni check check respect default image settings Signed-off-by: Jakub Jaruszewski * K8SPG-792 Add unit tests for default image behaviour Signed-off-by: Jakub Jaruszewski * K8SPG-792 Add comments regarding changed upstream func Signed-off-by: Jakub Jaruszewski * K8SPG-792 Use table for tests Signed-off-by: Jakub Jaruszewski * K8SPG-792 Fix gofmt warning Signed-off-by: Jakub Jaruszewski --------- Signed-off-by: Jakub Jaruszewski Co-authored-by: Viacheslav Sarzhan Co-authored-by: George Kechagias --- internal/config/config.go | 22 +++++-- percona/controller/pgcluster/controller.go | 4 +- .../v2/perconapgcluster_types.go | 7 +++ .../v2/perconapgcluster_types_test.go | 60 +++++++++++++++++++ 4 files changed, 85 insertions(+), 8 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index 783f56c3b0..032663fea9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -99,18 +99,28 @@ func PGExporterContainerImage(cluster *v1beta1.PostgresCluster) string { return defaultFromEnv(image, "RELATED_IMAGE_PGEXPORTER") } -// PostgresContainerImage returns the container image to use for PostgreSQL. -func PostgresContainerImage(cluster *v1beta1.PostgresCluster) string { - image := cluster.Spec.Image - key := "RELATED_IMAGE_POSTGRES_" + fmt.Sprint(cluster.Spec.PostgresVersion) +// PostgresContainerImageString returns the container image to use for PostgreSQL (from string params). +// This func copies logic from original PostgresContainerImage as is, leaving PostgresContainerImage as a wrapper for upstream compatibility +func PostgresContainerImageString(image string, postgresVersion int, postGISVersion string) string { + key := "RELATED_IMAGE_POSTGRES_" + fmt.Sprint(postgresVersion) - if version := cluster.Spec.PostGISVersion; version != "" { - key += "_GIS_" + version + if postGISVersion != "" { + key += "_GIS_" + postGISVersion } return defaultFromEnv(image, key) } +// PostgresContainerImage returns the container image to use for PostgreSQL. +// Made as a wrapper of PostgresContainerImageString for compat reasons +func PostgresContainerImage(cluster *v1beta1.PostgresCluster) string { + image := cluster.Spec.Image + postgresVersion := cluster.Spec.PostgresVersion + postGISVersion := cluster.Spec.PostGISVersion + + return PostgresContainerImageString(image, postgresVersion, postGISVersion) +} + // PGONamespace returns the namespace where the PGO is running, // based on the env var from the DownwardAPI // If no env var is found, returns "" diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 128e682c75..f3e0d03928 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -424,7 +424,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, Containers: []corev1.Container{ { Name: pNaming.ContainerPatroniVersionCheck, - Image: cr.Spec.Image, + Image: cr.PostgresImage(), Command: []string{ "bash", }, @@ -807,7 +807,7 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr for i := 0; i < len(cr.Spec.InstanceSets); i++ { set := &cr.Spec.InstanceSets[i] set.InitContainers = append(set.InitContainers, extensions.ExtensionRelocatorContainer( - cr, cr.Spec.Image, cr.Spec.ImagePullPolicy, cr.Spec.PostgresVersion, + cr, cr.PostgresImage(), cr.Spec.ImagePullPolicy, cr.Spec.PostgresVersion, )) set.InitContainers = append(set.InitContainers, extensions.ExtensionInstallerContainer( cr, diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index bcb1d2e163..a63503c4f8 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -10,6 +10,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "github.com/percona/percona-postgresql-operator/internal/config" "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/internal/naming" pNaming "github.com/percona/percona-postgresql-operator/percona/naming" @@ -245,6 +246,12 @@ func (cr *PerconaPGCluster) Default() { } } +func (cr *PerconaPGCluster) PostgresImage() string { + image := cr.Spec.Image + postgresVersion := cr.Spec.PostgresVersion + return config.PostgresContainerImageString(image, postgresVersion, "") +} + func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crunchyv1beta1.PostgresCluster, scheme *runtime.Scheme) (*crunchyv1beta1.PostgresCluster, error) { log := logging.FromContext(ctx) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go index d5ef124895..228056957a 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go @@ -1,6 +1,8 @@ package v2 import ( + "fmt" + "os" "testing" "gotest.tools/v3/assert" @@ -41,3 +43,61 @@ func TestPerconaPGCluster_BackupsEnabled(t *testing.T) { }) } } + +func TestPerconaPGCluster_PostgresImage(t *testing.T) { + cluster := new(PerconaPGCluster) + cluster.Default() + + postgresVersion := 16 + testDefaultImage := fmt.Sprintf("test_default_image:%d", postgresVersion) + testSpecificImage := fmt.Sprintf("test_defined_image:%d", postgresVersion) + testEnv := fmt.Sprintf("RELATED_IMAGE_POSTGRES_%d", postgresVersion) + + cluster.Spec.PostgresVersion = postgresVersion + + tests := map[string]struct { + expectedImage string + setImage string + envImage string + }{ + "Spec.Image should be empty by default": { + expectedImage: "", + setImage: "", + envImage: "", + }, + "Spec.Image should use env variables if present": { + expectedImage: testDefaultImage, + setImage: "", + envImage: testDefaultImage, + }, + "Spec.Image should use defined variable": { + expectedImage: testSpecificImage, + setImage: testSpecificImage, + envImage: testDefaultImage, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + + cluster.Spec.Image = tt.setImage + + if tt.envImage != "" { + err := os.Setenv(testEnv, tt.envImage) + + if err != nil { + t.Fatalf("Failed to set %s env variable: %v", testEnv, err) + } + + defer func() { + err := os.Unsetenv(testEnv) + if err != nil { + t.Errorf("Failed to unset %s env variable: %v", testEnv, err) + } + }() + } + + assert.Equal(t, cluster.PostgresImage(), tt.expectedImage) + }) + } +} From 16dc36eaa921b1bafcd9b215c9f89b503391c834 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Mon, 30 Jun 2025 19:28:40 +0300 Subject: [PATCH 059/300] K8SPG-812 fix upgrade image (#1192) --- deploy/upgrade.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 1731919fae..d5a275bf49 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,7 +4,7 @@ metadata: name: cluster1-15-to-16 spec: postgresClusterName: cluster1 - image: perconalab/percona-postgresql-operator:main + image: perconalab/percona-postgresql-operator:main-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 toPostgresImage: perconalab/percona-postgresql-operator:main-ppg17-postgres From d29085b3a5e816433af1573155c9dcb195abb577 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Mon, 30 Jun 2025 20:57:49 +0300 Subject: [PATCH 060/300] K8SPG-804: Fix `internal.percona.com/delete-backup` finalizer (#1182) * Fix `internal.percona.com/delete-backup` finalizer * i think this is a proper fix * one more fix * final fix * update the commets * delete return since we are getting latest cluster object * fix tests * add dependency * final lint fix --------- Co-authored-by: Viacheslav Sarzhan --- .../controller/postgrescluster/pgbackrest.go | 25 +++++++- percona/controller/pgbackup/controller.go | 59 +++++++------------ 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index d470daab30..b3e330b71d 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -2303,7 +2303,28 @@ func (r *Reconciler) reconcileDedicatedRepoHost(ctx context.Context, // manually by the end-user func (r *Reconciler) reconcileManualBackup(ctx context.Context, postgresCluster *v1beta1.PostgresCluster, manualBackupJobs []*batchv1.Job, - serviceAccount *corev1.ServiceAccount, instances *observedInstances) error { + serviceAccount *corev1.ServiceAccount, instances *observedInstances, +) error { + // K8SPG-804: Get the current state of PostgresCluster. + // It's necessary to make internal.percona.com/delete-backup finalizer work. + // Because the reconcileManualBackup can get an outdated postgresCluster, + // resulting in a duplicated backup jobs per one pg-backup resources. + // For more information check the K8SPG-804 PR description. + currentPostgresCluster := new(v1beta1.PostgresCluster) + err := r.Client.Get(ctx, client.ObjectKeyFromObject(postgresCluster), currentPostgresCluster) + if client.IgnoreNotFound(err) != nil { + return err + } + + // refPostgresCluster keeps pointer to the postgresCluster which is used in other reconcile functions + // It should be used to assign values to the postgresCluster inside this function + refPostgresCluster := postgresCluster + + // If it's the first run of reconcileManualBackup .Status will be nil. + // Nothing will happen if we keep the old postgresCluster. + if !apierrors.IsNotFound(err) && currentPostgresCluster.Status.PGBackRest != nil { + postgresCluster = currentPostgresCluster + } manualAnnotation := postgresCluster.GetAnnotations()[naming.PGBackRestBackup] manualStatus := postgresCluster.Status.PGBackRest.ManualBackup @@ -2396,7 +2417,7 @@ func (r *Reconciler) reconcileManualBackup(ctx context.Context, meta.RemoveStatusCondition(&postgresCluster.Status.Conditions, ConditionManualBackupSuccessful) - postgresCluster.Status.PGBackRest.ManualBackup = manualStatus + refPostgresCluster.Status.PGBackRest.ManualBackup = manualStatus } // if the status shows the Job is no longer in progress, then simply exit (which means a Job diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index 0661635c9d..e39a40837e 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -4,7 +4,6 @@ import ( "context" "path" "slices" - "strings" "time" "github.com/pkg/errors" @@ -514,10 +513,17 @@ func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBa if err != nil { return nil, errors.Wrap(err, "get backup in progress") } + if runningBackup != pgBackup.Name { + // This block only runs after all finalizer operations are complete. + // Or, it runs when the user deletes a backup object that never started. + // In both cases, treat this as the function's exit point. + return nil, nil } + // deleteAnnotation deletes the annotation from the PerconaPGCluster + // and returns true when it's deleted from crunchy PostgresCluster. deleteAnnotation := func(annotation string) (bool, error) { pgCluster := new(v1beta1.PostgresCluster) if err := c.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: pgBackup.Namespace}, pgCluster); err != nil { @@ -555,24 +561,20 @@ func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBa return nil, errors.Wrapf(err, "delete %s annotation", naming.PGBackRestBackup) } if !deleted { - // We should wait until the crunchy reconciler is finished. - // If we delete the job labels without waiting for the reconcile to finish, the Crunchy reconciler will - // receive the pgcluster with the "naming.PGBackRestBackup" annotation, but will not find the manual backup job. - // It will attempt to create a new job with the same name, failing and resulting in a scary error in the logs. + // We should wait until the annotation is deleted from crunchy cluster. return &reconcile.Result{RequeueAfter: time.Second * 5}, nil } // Remove PGBackRest labels to prevent the job from being - // deleted by the cleanupRepoResources method. + // deleted by the cleanupRepoResources method and included in + // repoResources.manualBackupJobs used in reconcileManualBackup method if job != nil { if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { j := new(batchv1.Job) if err := c.Get(ctx, client.ObjectKeyFromObject(job), j); err != nil { - if k8serrors.IsNotFound(err) { - return nil - } return errors.Wrap(err, "get job") } + for k := range naming.PGBackRestLabels(pgBackup.Spec.PGCluster) { delete(j.Labels, k) } @@ -583,6 +585,7 @@ func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBa } } + // We should delete the pgbackrest status to be able to recreate backups with the same name. if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { pgCluster := new(v1beta1.PostgresCluster) if err := c.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: pgBackup.Namespace}, pgCluster); err != nil { @@ -595,39 +598,19 @@ func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBa return nil, errors.Wrap(err, "update postgrescluster") } - deleted, err = deleteAnnotation(pNaming.AnnotationBackupInProgress) + _, err = deleteAnnotation(pNaming.AnnotationBackupInProgress) if err != nil { return nil, errors.Wrapf(err, "delete %s annotation", pNaming.AnnotationBackupInProgress) } - if !deleted { - return &reconcile.Result{RequeueAfter: time.Second * 5}, nil - } - - if job != nil && checkBackupJob(job) != v2.BackupSucceeded { - // Remove all crunchy labels to prevent the job from being included in - // repoResources.manualBackupJobs used in reconcileManualBackup method. - if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { - j := new(batchv1.Job) - if err := c.Get(ctx, client.ObjectKeyFromObject(job), j); err != nil { - if k8serrors.IsNotFound(err) { - return nil - } - return errors.Wrap(err, "get job") - } - - for k := range j.Labels { - if strings.HasPrefix(k, pNaming.PrefixCrunchy) { - delete(j.Labels, k) - } - } - - return c.Update(ctx, j) - }); err != nil { - return nil, errors.Wrap(err, "delete backup job labels") - } - } + // Do not add any code after this comment. + // + // The code after the comment may or may not execute, depending on whether the + // crunchy cluster removes the AnnotationBackupInProgress annotation in time. + // + // Once AnnotationBackupInProgress is deleted, the successful return of finalizer must happen inside the + // `if runningBackup != pgBackup.Name { ... }` block. - return nil, nil + return &reconcile.Result{RequeueAfter: time.Second * 5}, nil } func startBackup(ctx context.Context, c client.Client, pb *v2.PerconaPGBackup) error { From e3525fe5e4ed2e28ea1ccb49155da929eff23b8e Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Tue, 1 Jul 2025 08:58:22 +0300 Subject: [PATCH 061/300] K8SPG-613: fix .spec.initContainer (#1191) * K8SPG-613: fix .spec.initContainer https://perconadev.atlassian.net/browse/K8SPG-613 * revert formatting * fix lint --------- Co-authored-by: Eleonora Zinchenko Co-authored-by: Viacheslav Sarzhan --- ...es-operator.crunchydata.com_postgresclusters.yaml | 6 ++++++ .../pgv2.percona.com_perconapgclusters.yaml | 6 ++++++ .../bases/pgv2.percona.com_perconapgclusters.yaml | 6 ++++++ ...es-operator.crunchydata.com_postgresclusters.yaml | 6 ++++++ deploy/bundle.yaml | 12 ++++++++++++ deploy/crd.yaml | 12 ++++++++++++ deploy/cw-bundle.yaml | 12 ++++++++++++ internal/controller/postgrescluster/pgbackrest.go | 1 + internal/patroni/reconcile.go | 1 + percona/k8s/util.go | 6 +++++- percona/k8s/util_test.go | 2 +- .../v1beta1/postgrescluster_types.go | 1 + 12 files changed, 69 insertions(+), 2 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 3e527f75fd..afb2a25a8c 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -649,6 +649,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -8885,6 +8887,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -11718,6 +11722,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 67692654b2..050e83ca42 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -807,6 +807,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -8690,6 +8692,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -10151,6 +10155,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 5f52ac97d6..871e89b05e 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -1214,6 +1214,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -9097,6 +9099,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -10558,6 +10562,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 74d4c1ef1d..881887b0ec 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -641,6 +641,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -8840,6 +8842,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -11660,6 +11664,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 038c2b40ff..f2531bfc34 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -1511,6 +1511,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -9394,6 +9396,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -10855,6 +10859,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- @@ -27149,6 +27155,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -35348,6 +35356,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -38168,6 +38178,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- diff --git a/deploy/crd.yaml b/deploy/crd.yaml index d79c211c89..ed6416046b 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -1511,6 +1511,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -9394,6 +9396,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -10855,6 +10859,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- @@ -27149,6 +27155,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -35348,6 +35356,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -38168,6 +38178,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 8f3313a07e..be92efa6b7 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -1511,6 +1511,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -9394,6 +9396,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -10855,6 +10859,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- @@ -27149,6 +27155,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object jobs: description: Jobs field allows configuration for all backup @@ -35348,6 +35356,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object instances: description: |- @@ -38168,6 +38178,8 @@ spec: More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ type: object type: object + required: + - image type: object initContainers: description: |- diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index b3e330b71d..76eb8d5606 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -843,6 +843,7 @@ func generateBackupJobSpecIntent(ctx context.Context, postgresCluster *v1beta1.P } initContainers = []corev1.Container{ k8s.InitContainer( + postgresCluster, naming.PGBackRestRepoContainerName, initImage, postgresCluster.Spec.ImagePullPolicy, diff --git a/internal/patroni/reconcile.go b/internal/patroni/reconcile.go index 940f8a88e4..4f10093428 100644 --- a/internal/patroni/reconcile.go +++ b/internal/patroni/reconcile.go @@ -148,6 +148,7 @@ func InstancePod(ctx context.Context, // K8SPG-708 instanceInitContainer adds the instance init container func instanceInitContainer(cluster *v1beta1.PostgresCluster, container *corev1.Container, instancePod *corev1.PodTemplateSpec, inInstanceSpec *v1beta1.PostgresInstanceSetSpec, initImage string) { instancePod.Spec.InitContainers = append(instancePod.Spec.InitContainers, k8s.InitContainer( + cluster, naming.ContainerDatabase, initImage, cluster.Spec.ImagePullPolicy, diff --git a/percona/k8s/util.go b/percona/k8s/util.go index e90c5e382f..be89708851 100644 --- a/percona/k8s/util.go +++ b/percona/k8s/util.go @@ -39,7 +39,7 @@ func GetWatchNamespace() (string, error) { return ns, nil } -func InitContainer(componentName, image string, +func InitContainer(cluster *v1beta1.PostgresCluster, componentName, image string, pullPolicy corev1.PullPolicy, secCtx *corev1.SecurityContext, resources corev1.ResourceRequirements, @@ -47,9 +47,13 @@ func InitContainer(componentName, image string, ) corev1.Container { if component != nil && component.GetInitContainer() != nil && component.GetInitContainer().Resources != nil { resources = *component.GetInitContainer().Resources + } else if ic := cluster.Spec.InitContainer; ic != nil && ic.Resources != nil { + resources = *ic.Resources } if component != nil && component.GetInitContainer() != nil && component.GetInitContainer().ContainerSecurityContext != nil { secCtx = component.GetInitContainer().ContainerSecurityContext + } else if ic := cluster.Spec.InitContainer; ic != nil && ic.ContainerSecurityContext != nil { + secCtx = ic.ContainerSecurityContext } volumeMounts := []corev1.VolumeMount{ diff --git a/percona/k8s/util_test.go b/percona/k8s/util_test.go index d35ca18c2f..714239d273 100644 --- a/percona/k8s/util_test.go +++ b/percona/k8s/util_test.go @@ -206,7 +206,7 @@ volumeMounts: t.Setenv("OPERATOR_NAMESPACE", cr.Namespace) cr := tt.getCluster().DeepCopy() - container := InitContainer(tt.component, tt.image, tt.pullPolicy, tt.secCtx, tt.resources, tt.getComponent(cr)) + container := InitContainer(tt.getCluster(), tt.component, tt.image, tt.pullPolicy, tt.secCtx, tt.resources, tt.getComponent(cr)) data, err := yaml.Marshal(container) if err != nil { t.Fatal(err) diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index ed89da05cb..b9551cecb0 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -194,6 +194,7 @@ type PostgresClusterSpec struct { } type InitContainerSpec struct { + // +kubebuilder:validation:Required Image string `json:"image,omitempty"` Resources *corev1.ResourceRequirements `json:"resources,omitempty"` ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"` From d259ba1bc9c39e93ae700ad54e81062e7ec3978b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:10:04 +0300 Subject: [PATCH 062/300] CLOUD-727: Bump golang.org/x/tools from 0.33.0 to 0.34.0 (#1193) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.33.0 to 0.34.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.33.0...v0.34.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.34.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 370f6003b9..97b1663021 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.38.0 + golang.org/x/crypto v0.39.0 google.golang.org/grpc v1.73.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.33.2 @@ -54,7 +54,7 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - golang.org/x/mod v0.24.0 // indirect + golang.org/x/mod v0.25.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect ) @@ -114,14 +114,14 @@ require ( go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.40.0 // indirect + golang.org/x/net v0.41.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect - golang.org/x/sync v0.14.0 // indirect + golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.25.0 // indirect + golang.org/x/text v0.26.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.33.0 + golang.org/x/tools v0.34.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect diff --git a/go.sum b/go.sum index e9a6216308..03b842213e 100644 --- a/go.sum +++ b/go.sum @@ -245,29 +245,29 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= -golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= -golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= -golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -286,8 +286,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= -golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -295,8 +295,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= -golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 0ffb49f8d6c2ea7341f4841f343d95143350d2c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:11:43 +0300 Subject: [PATCH 063/300] CLOUD-727: Bump aquasecurity/trivy-action from 0.30.0 to 0.31.0 (#1198) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.30.0 to 0.31.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.30.0...0.31.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-version: 0.31.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- .github/workflows/scan.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 56c9437d60..da69cf2c11 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -31,7 +31,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/arm64) - uses: aquasecurity/trivy-action@0.30.0 + uses: aquasecurity/trivy-action@0.31.0 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64' format: 'table' @@ -50,7 +50,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/amd64) - uses: aquasecurity/trivy-action@0.30.0 + uses: aquasecurity/trivy-action@0.31.0 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64' format: 'table' From 9536831438b69678af038621f150771042e00fa9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:19:35 +0300 Subject: [PATCH 064/300] CLOUD-727: Bump github.com/grpc-ecosystem/grpc-gateway/v2 (#1194) Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.26.3 to 2.27.1. - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.26.3...v2.27.1) --- updated-dependencies: - dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2 dependency-version: 2.27.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 97b1663021..b7f9ad49ac 100644 --- a/go.mod +++ b/go.mod @@ -82,7 +82,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -115,7 +115,7 @@ require ( go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.41.0 // indirect - golang.org/x/oauth2 v0.28.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.15.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/term v0.32.0 // indirect @@ -123,8 +123,8 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.34.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 03b842213e..14272c9e1a 100644 --- a/go.sum +++ b/go.sum @@ -89,8 +89,8 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= @@ -260,8 +260,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -303,10 +303,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= -google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= +google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= From 312730f1261d61a59d88341122da0f063b9c5ab8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 12:30:35 +0300 Subject: [PATCH 065/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp (#1196) Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) from 1.35.0 to 1.37.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.35.0...v1.37.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp dependency-version: 1.37.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b7f9ad49ac..c05822ab5b 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 go.opentelemetry.io/otel v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 go.opentelemetry.io/otel/sdk v1.37.0 go.opentelemetry.io/otel/trace v1.37.0 @@ -43,6 +43,7 @@ require ( ) require ( + github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect @@ -65,7 +66,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/bool64/shared v0.1.5 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect diff --git a/go.sum b/go.sum index 14272c9e1a..6be51a433f 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/bool64/dev v0.2.29 h1:x+syGyh+0eWtOzQ1ItvLzOGIWyNWnyjXpHIcpF2HvL4= github.com/bool64/dev v0.2.29/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= +github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -219,8 +219,8 @@ go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= From 1681f23d009b502173cdb7d013e5cec598588bc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 12:42:01 +0300 Subject: [PATCH 066/300] CLOUD-727: Bump sigs.k8s.io/yaml from 1.4.0 to 1.5.0 (#1195) Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/kubernetes-sigs/yaml/releases) - [Changelog](https://github.com/kubernetes-sigs/yaml/blob/master/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/yaml/compare/v1.4.0...v1.5.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/yaml dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 3 ++- go.sum | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index c05822ab5b..066129fe58 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( k8s.io/client-go v0.33.2 k8s.io/component-base v0.33.2 sigs.k8s.io/controller-runtime v0.21.0 - sigs.k8s.io/yaml v1.4.0 + sigs.k8s.io/yaml v1.5.0 ) require ( @@ -55,6 +55,7 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/mod v0.25.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/go.sum b/go.sum index 6be51a433f..aca8f36098 100644 --- a/go.sum +++ b/go.sum @@ -241,6 +241,10 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= +go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -357,5 +361,6 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= +sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= From f9e51245bd88da6487d5d92f24edf55cedd9378b Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Tue, 1 Jul 2025 20:29:49 +0300 Subject: [PATCH 067/300] K8SPG-613: use random location for start-from-backup source (#1203) --- e2e-tests/functions | 3 +- .../01-create-source-cluster.yaml | 3 +- .../start-from-backup/06-create-cluster.yaml | 4 +- e2e-tests/tests/start-from-backup/cr.yaml | 496 ------------------ 4 files changed, 6 insertions(+), 500 deletions(-) delete mode 100644 e2e-tests/tests/start-from-backup/cr.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index cacd8d2afe..0a28f8fe0e 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -170,6 +170,7 @@ get_cr() { cr_name=${test_name} fi local repo_path=$2 + local source_path=$3 yq eval ' .metadata.name = "'${cr_name}'" | @@ -210,7 +211,7 @@ get_cr() { yq eval -i ' .spec.dataSource.pgbackrest.configuration = [{"secret":{"name":"'${test_name}'-pgbackrest-secrets"}}] | .spec.dataSource.pgbackrest.stanza = "db" | - .spec.dataSource.pgbackrest.global.repo1-path = "/backrestrepo/postgres-operator/demand-backup-ppg'$PG_VER'/repo1" | + .spec.dataSource.pgbackrest.global.repo1-path = "'${source_path}'" | .spec.dataSource.pgbackrest.repo = {"name":"repo1","s3":{"bucket":"'$BUCKET'","endpoint":"s3.amazonaws.com","region":"us-east-1"}} ' $TEMP_DIR/cr.yaml fi diff --git a/e2e-tests/tests/start-from-backup/01-create-source-cluster.yaml b/e2e-tests/tests/start-from-backup/01-create-source-cluster.yaml index f1bf49153a..422b246fa4 100644 --- a/e2e-tests/tests/start-from-backup/01-create-source-cluster.yaml +++ b/e2e-tests/tests/start-from-backup/01-create-source-cluster.yaml @@ -8,5 +8,6 @@ commands: source ../../functions - get_cr "start-from-backup-source" "demand-backup-ppg$PG_VER" \ + get_cr "start-from-backup-source" ${RANDOM} \ | kubectl -n "${NAMESPACE}" apply -f - + \ No newline at end of file diff --git a/e2e-tests/tests/start-from-backup/06-create-cluster.yaml b/e2e-tests/tests/start-from-backup/06-create-cluster.yaml index b18ea7463d..048dac443b 100644 --- a/e2e-tests/tests/start-from-backup/06-create-cluster.yaml +++ b/e2e-tests/tests/start-from-backup/06-create-cluster.yaml @@ -7,5 +7,5 @@ commands: set -o xtrace source ../../functions - - get_cr "start-from-backup" ${RANDOM}| kubectl -n "${NAMESPACE}" apply -f - + destination=$(kubectl get perconapgbackup -n "${NAMESPACE}" start-from-backup-source-full-s3 -o jsonpath='{.status.destination}' | sed 's/^s3:\/\/pg-operator-testing//g') + get_cr "start-from-backup" ${RANDOM} ${destination} | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/start-from-backup/cr.yaml b/e2e-tests/tests/start-from-backup/cr.yaml deleted file mode 100644 index 6c11b47213..0000000000 --- a/e2e-tests/tests/start-from-backup/cr.yaml +++ /dev/null @@ -1,496 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: start-from-backup-source - labels: - e2e: start-from-backup-source -# finalizers: -# - percona.com/delete-pvc -# - percona.com/delete-ssl -spec: - crVersion: 2.5.1 - # secrets: - # customRootCATLSSecret: - # name: cluster1-ca-cert - # items: - # - key: "tls.crt" - # path: "root.crt" - # - key: "tls.key" - # path: "root.key" - # customTLSSecret: - # name: cluster1-cert - # customReplicationTLSSecret: - # name: replication1-cert - - # standby: - # enabled: true - # host: "" - # port: "" - # repoName: repo1 - - # openshift: true - - # users: - # - name: rhino - # databases: - # - zoo - # options: "SUPERUSER" - # password: - # type: ASCII - # secretName: "rhino-credentials" - - # databaseInitSQL: - # key: init.sql - # name: cluster1-init-sql - - # pause: true - # unmanaged: true - # dataSource: - # postgresCluster: - # clusterName: cluster1 - # clusterNamespace: cluster1-namespace - # repoName: repo1 - # options: - # - --type=time - # - --target="2021-06-09 14:15:11-04" - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # pgbackrest: - # stanza: db - # configuration: - # - secret: - # name: pgo-s3-creds - # global: - # repo1-path: /pgbackrest/postgres-operator/hippo/repo1 - # repo: - # name: repo1 - # s3: - # bucket: "my-bucket" - # endpoint: "s3.ca-central-1.amazonaws.com" - # region: "ca-central-1" - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # volumes: - # pgDataVolume: - # pvcName: cluster1 - # directory: cluster1 - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # annotations: - # test-annotation: value - # labels: - # test-label: value - # pgWALVolume: - # pvcName: cluster1-pvc-name - # directory: some-dir - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # annotations: - # test-annotation: value - # labels: - # test-label: value - # pgBackRestVolume: - # pvcName: cluster1-pgbr-repo - # directory: cluster1-backrest-shared-repo - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # annotations: - # test-annotation: value - # labels: - # test-label: value - image: perconalab/percona-postgresql-operator:main-ppg16-postgres - imagePullPolicy: Always - postgresVersion: 16 - # port: 5432 - - # expose: - # annotations: - # my-annotation: value1 - # labels: - # my-label: value2 - # type: LoadBalancer - # loadBalancerSourceRanges: - # - 10.0.0.0/8 - # exposeReplicas: - # annotations: - # my-annotation: value1 - # labels: - # my-label: value2 - # type: LoadBalancer - # loadBalancerSourceRanges: - # - 10.0.0.0/8 - instances: - - name: instance1 - replicas: 3 - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 1 - podAffinityTerm: - labelSelector: - matchLabels: - postgres-operator.crunchydata.com/data: postgres - topologyKey: kubernetes.io/hostname - # resources: - # limits: - # cpu: 2.0 - # memory: 4Gi - # containers: - # replicaCertCopy: - # resources: - # limits: - # cpu: 200m - # memory: 128Mi - # sidecars: - # - name: testcontainer - # image: mycontainer1:latest - # - name: testcontainer2 - # image: mycontainer1:latest - # - # topologySpreadConstraints: - # - maxSkew: 1 - # topologyKey: my-node-label - # whenUnsatisfiable: DoNotSchedule - # labelSelector: - # matchLabels: - # postgres-operator.crunchydata.com/instance-set: instance1 - # - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # - # priorityClassName: high-priority - # - # securityContext: - # fsGroup: 1001 - # runAsUser: 1001 - # runAsNonRoot: true - # fsGroupChangePolicy: "OnRootMismatch" - # runAsGroup: 1001 - # seLinuxOptions: - # type: spc_t - # level: s0:c123,c456 - # seccompProfile: - # type: Localhost - # localhostProfile: localhost/profile.json - # supplementalGroups: - # - 1001 - # sysctls: - # - name: net.ipv4.tcp_keepalive_time - # value: "600" - # - name: net.ipv4.tcp_keepalive_intvl - # value: "60" - # - # walVolumeClaimSpec: - # storageClassName: standard - # accessModes: - # - ReadWriteOnce - # resources: - # requests: - # storage: 1Gi - # - dataVolumeClaimSpec: - # storageClassName: standard - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - # limits: - # storage: 5Gi - # tablespaceVolumes: - # - name: user - # dataVolumeClaimSpec: - # accessModes: - # - 'ReadWriteOnce' - # resources: - # requests: - # storage: 1Gi - - proxy: - pgBouncer: - replicas: 3 - image: perconalab/percona-postgresql-operator:main-ppg16-pgbouncer - # exposeSuperusers: true - # resources: - # limits: - # cpu: 200m - # memory: 128Mi - # containers: - # pgbouncerConfig: - # resources: - # limits: - # cpu: 200m - # memory: 128Mi - # - # expose: - # annotations: - # my-annotation: value1 - # labels: - # my-label: value2 - # type: LoadBalancer - # loadBalancerSourceRanges: - # - 10.0.0.0/8 - # - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 1 - podAffinityTerm: - labelSelector: - matchLabels: - postgres-operator.crunchydata.com/role: pgbouncer - topologyKey: kubernetes.io/hostname - # - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # - # securityContext: - # fsGroup: 1001 - # runAsUser: 1001 - # runAsNonRoot: true - # fsGroupChangePolicy: "OnRootMismatch" - # runAsGroup: 1001 - # seLinuxOptions: - # type: spc_t - # level: s0:c123,c456 - # seccompProfile: - # type: Localhost - # localhostProfile: localhost/profile.json - # supplementalGroups: - # - 1001 - # sysctls: - # - name: net.ipv4.tcp_keepalive_time - # value: "600" - # - name: net.ipv4.tcp_keepalive_intvl - # value: "60" - # - # topologySpreadConstraints: - # - maxSkew: 1 - # topologyKey: my-node-label - # whenUnsatisfiable: ScheduleAnyway - # labelSelector: - # matchLabels: - # postgres-operator.crunchydata.com/role: pgbouncer - # - # sidecars: - # - name: bouncertestcontainer1 - # image: mycontainer1:latest - # - # customTLSSecret: - # name: keycloakdb-pgbouncer.tls - # - # config: - # global: - # pool_mode: transaction - - backups: - # trackLatestRestorableTime: true - pgbackrest: - # metadata: - # labels: - image: perconalab/percona-postgresql-operator:main-ppg16-pgbackrest - # - # containers: - # pgbackrest: - # resources: - # limits: - # cpu: 200m - # memory: 128Mi - # pgbackrestConfig: - # resources: - # limits: - # cpu: 200m - # memory: 128Mi - # - # configuration: - # - secret: - # name: cluster1-pgbackrest-secrets - # jobs: - # priorityClassName: high-priority - # resources: - # limits: - # cpu: 200m - # memory: 128Mi - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # - # securityContext: - # fsGroup: 1001 - # runAsUser: 1001 - # runAsNonRoot: true - # fsGroupChangePolicy: "OnRootMismatch" - # runAsGroup: 1001 - # seLinuxOptions: - # type: spc_t - # level: s0:c123,c456 - # seccompProfile: - # type: Localhost - # localhostProfile: localhost/profile.json - # supplementalGroups: - # - 1001 - # sysctls: - # - name: net.ipv4.tcp_keepalive_time - # value: "600" - # - name: net.ipv4.tcp_keepalive_intvl - # value: "60" - # - # global: - # repo1-retention-full: "14" - # repo1-retention-full-type: time - # repo1-path: /pgbackrest/postgres-operator/cluster1/repo1 - # repo1-cipher-type: aes-256-cbc - # repo1-s3-uri-style: path - # repo2-path: /pgbackrest/postgres-operator/cluster1-multi-repo/repo2 - # repo3-path: /pgbackrest/postgres-operator/cluster1-multi-repo/repo3 - # repo4-path: /pgbackrest/postgres-operator/cluster1-multi-repo/repo4 - repoHost: - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 1 - podAffinityTerm: - labelSelector: - matchLabels: - postgres-operator.crunchydata.com/data: pgbackrest - topologyKey: kubernetes.io/hostname - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - # priorityClassName: high-priority - # - # topologySpreadConstraints: - # - maxSkew: 1 - # topologyKey: my-node-label - # whenUnsatisfiable: ScheduleAnyway - # labelSelector: - # matchLabels: - # postgres-operator.crunchydata.com/pgbackrest: "" - # - # securityContext: - # fsGroup: 1001 - # runAsUser: 1001 - # runAsNonRoot: true - # fsGroupChangePolicy: "OnRootMismatch" - # runAsGroup: 1001 - # seLinuxOptions: - # type: spc_t - # level: s0:c123,c456 - # seccompProfile: - # type: Localhost - # localhostProfile: localhost/profile.json - # supplementalGroups: - # - 1001 - # sysctls: - # - name: net.ipv4.tcp_keepalive_time - # value: "600" - # - name: net.ipv4.tcp_keepalive_intvl - # value: "60" - # - manual: - repoName: repo1 - options: - - --type=full - repos: - - name: repo1 - schedules: - full: "0 0 * * 6" - # differential: "0 1 * * 1-6" - # incremental: "0 1 * * 1-6" - volume: - volumeClaimSpec: - # storageClassName: standard - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi - # - name: repo2 - # s3: - # bucket: "" - # endpoint: "" - # region: "" - # - name: repo3 - # gcs: - # bucket: "" - # - name: repo4 - # azure: - # container: "" - # - # restore: - # repoName: repo1 - # tolerations: - # - effect: NoSchedule - # key: role - # operator: Equal - # value: connection-poolers - - pmm: - enabled: false - image: perconalab/pmm-client:dev-latest - # imagePullPolicy: IfNotPresent - secret: start-from-backup-source-pmm-secret - serverHost: monitoring-service - users: - - name: postgres - password: - type: AlphaNumeric - - name: start-from-backup-source - password: - type: AlphaNumeric -# querySource: pgstatmonitor -# patroni: -# # Some values of the Liveness/Readiness probes of the patroni container are calculated using syncPeriodSeconds by the following formulas: -# # - timeoutSeconds: syncPeriodSeconds / 2; -# # - periodSeconds: syncPeriodSeconds; -# # - failureThreshold: leaderLeaseDurationSeconds / syncPeriodSeconds. -# syncPeriodSeconds: 10 # default: 10 -# leaderLeaseDurationSeconds: 30 # default: 30 -# dynamicConfiguration: -# postgresql: -# parameters: -# max_parallel_workers: 2 -# max_worker_processes: 2 -# shared_buffers: 1GB -# work_mem: 2MB -# extensions: -# image: percona/percona-postgresql-operator:2.5.1 -# imagePullPolicy: Always -# storage: -# type: s3 -# bucket: pg-extensions -# region: eu-central-1 -# endpoint: s3.eu-central-1.amazonaws.com -# secret: -# name: cluster1-extensions-secret -# builtin: -# pg_stat_monitor: true -# pg_audit: true -# custom: -# - name: pg_cron -# version: 1.6.1 From 8a4d0b789a548a7ed03b00fa27eff2ddaa4b0077 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 2 Jul 2025 13:13:59 +0200 Subject: [PATCH 068/300] K8SPG-571 public schema access fix (#1201) * K8SPG-571 fix public schema access * fix --- internal/postgres/users.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/internal/postgres/users.go b/internal/postgres/users.go index c878ba1a1d..52b7e861cb 100644 --- a/internal/postgres/users.go +++ b/internal/postgres/users.go @@ -8,6 +8,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "strings" pg_query "github.com/pganalyze/pg_query_go/v6" @@ -271,6 +272,9 @@ func grantUserAccessToPublicSchemaInPostgreSQL(ctx context.Context, exec Executo databases, _ := json.Marshal(user.Databases) + // Format the username as an identifier + username := fmt.Sprintf(`"%s"`, user.Name) + stdout, stderr, err := exec.ExecInDatabasesFromQuery(ctx, sql.String(), strings.Join([]string{ @@ -278,19 +282,18 @@ func grantUserAccessToPublicSchemaInPostgreSQL(ctx context.Context, exec Executo `SET client_min_messages = WARNING;`, // Grant all privileges on the public schema to the user - `GRANT ALL PRIVILEGES ON SCHEMA public TO :"username";`, + fmt.Sprintf(`GRANT ALL PRIVILEGES ON SCHEMA public TO %s;`, username), // Grant all privileges on existing tables and sequences in the public schema - `GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO :"username";`, - `GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO :"username";`, + fmt.Sprintf(`GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO %s;`, username), + fmt.Sprintf(`GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO %s;`, username), // Set default privileges for future objects created in the public schema - `ALTER DEFAULT PRIVILEGES FOR ROLE "username" IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO "username";`, - `ALTER DEFAULT PRIVILEGES FOR ROLE "username" IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO "username";`, + fmt.Sprintf(`ALTER DEFAULT PRIVILEGES FOR ROLE %s IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO %s;`, username, username), + fmt.Sprintf(`ALTER DEFAULT PRIVILEGES FOR ROLE %s IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO %s;`, username, username), }, "\n"), map[string]string{ "databases": string(databases), - "username": string(user.Name), "ON_ERROR_STOP": "on", // Abort when any one statement fails. "QUIET": "on", // Do not print successful commands to stdout. }, From 1f3f2949a676c174fbc149f8d612f915a77cdde1 Mon Sep 17 00:00:00 2001 From: Valmira Nogueira Date: Wed, 2 Jul 2025 21:41:10 -0300 Subject: [PATCH 069/300] Add pgvector extension test --- .../tests/pgvector-extension/00-assert.yaml | 24 +++++ .../00-deploy-operator.yaml | 13 +++ .../tests/pgvector-extension/01-assert.yaml | 88 +++++++++++++++++++ .../pgvector-extension/01-create-cluster.yaml | 13 +++ ...-verify-pgvector-extension-is-enabled.yaml | 26 ++++++ .../tests/pgvector-extension/03-assert.yaml | 88 +++++++++++++++++++ .../03-disable-pgvector-extension.yaml | 13 +++ ...verify-pgvector-extension-is-disabled.yaml | 31 +++++++ .../99-remove-cluster-gracefully.yaml | 21 +++++ 9 files changed, 317 insertions(+) create mode 100644 e2e-tests/tests/pgvector-extension/00-assert.yaml create mode 100644 e2e-tests/tests/pgvector-extension/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/pgvector-extension/01-assert.yaml create mode 100644 e2e-tests/tests/pgvector-extension/01-create-cluster.yaml create mode 100644 e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-enabled.yaml create mode 100644 e2e-tests/tests/pgvector-extension/03-assert.yaml create mode 100644 e2e-tests/tests/pgvector-extension/03-disable-pgvector-extension.yaml create mode 100644 e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-disabled.yaml create mode 100644 e2e-tests/tests/pgvector-extension/99-remove-cluster-gracefully.yaml diff --git a/e2e-tests/tests/pgvector-extension/00-assert.yaml b/e2e-tests/tests/pgvector-extension/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/pgvector-extension/00-deploy-operator.yaml b/e2e-tests/tests/pgvector-extension/00-deploy-operator.yaml new file mode 100644 index 0000000000..1aaca58be2 --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/00-deploy-operator.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client diff --git a/e2e-tests/tests/pgvector-extension/01-assert.yaml b/e2e-tests/tests/pgvector-extension/01-assert.yaml new file mode 100644 index 0000000000..903a1768da --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/01-assert.yaml @@ -0,0 +1,88 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: pgvector-extension + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: pgvector-extension + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: pgvector-extension-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: pgvector-extension + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: pgvector-extension + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: pgvector-extension + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: pgvector-extension + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +spec: + backups: + pgbackrest: {} +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: pgvector-extension +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml b/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml new file mode 100644 index 0000000000..bf7276223f --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "pgvector-extension" ${RANDOM} \ + | yq '.spec.extensions.builtin.pgvector=true' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-enabled.yaml b/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-enabled.yaml new file mode 100644 index 0000000000..0dd633eb61 --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-enabled.yaml @@ -0,0 +1,26 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + result=$(run_psql_local \ + "SELECT * FROM pg_extension WHERE extname = '\''vector'\'';" \ + "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") + + if [[ "$result" = *"vector"* ]]; then + echo "pgvector extension is enabled" + else + echo "pgvector extension is not enabled" + exit 1 + fi + + echo "Testing extension" + run_psql_local \ + "SELECT '\''[1,2,3]'\''::vector <-> '\''[3,2,1]'\''::vector;" \ + "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres" + + timeout: 360 diff --git a/e2e-tests/tests/pgvector-extension/03-assert.yaml b/e2e-tests/tests/pgvector-extension/03-assert.yaml new file mode 100644 index 0000000000..903a1768da --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/03-assert.yaml @@ -0,0 +1,88 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: pgvector-extension + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: pgvector-extension + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: pgvector-extension-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: pgvector-extension + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: pgvector-extension + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: pgvector-extension + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: pgvector-extension + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +spec: + backups: + pgbackrest: {} +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: pgvector-extension +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/pgvector-extension/03-disable-pgvector-extension.yaml b/e2e-tests/tests/pgvector-extension/03-disable-pgvector-extension.yaml new file mode 100644 index 0000000000..4fdba57a92 --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/03-disable-pgvector-extension.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "pgvector-extension" ${RANDOM} \ + | yq '.spec.extensions.builtin.pgvector=false' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-disabled.yaml b/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-disabled.yaml new file mode 100644 index 0000000000..dc61e541b0 --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-disabled.yaml @@ -0,0 +1,31 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + retries=10 + wait_seconds=5 + + for i in $(seq 1 $retries); do + echo "Attempt $i of $retries..." + + result=$(run_psql_local \ + "SELECT * FROM pg_extension WHERE extname = '\''vector'\'';" \ + "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") + + if [[ "$result" != *"vector"* ]]; then + echo "pgvector extension is disabled" + exit 0 + fi + + echo "pgvector extension still present, retrying in $wait_seconds seconds..." + sleep $wait_seconds + done + + echo "pgvector extension was not properly disabled" + exit 1 + timeout: 360 diff --git a/e2e-tests/tests/pgvector-extension/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/pgvector-extension/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..11c075f46b --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: pgvector-extension +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: pgvector-extension +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 From 8f9fb6f5dc9b1217e9296aed92e5281cfa28a18d Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 3 Jul 2025 11:21:14 +0300 Subject: [PATCH 070/300] K8SPG-613: add unit-test (#1204) * K8SPG-613: add unit-test https://perconadev.atlassian.net/browse/K8SPG-613 * address comments * cover pgbackrest --- percona/controller/pgbackup/controller.go | 6 +- .../controller/pgcluster/controller_test.go | 463 +++++++++++++++++- 2 files changed, 465 insertions(+), 4 deletions(-) diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index e39a40837e..be38cd09e8 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -490,7 +490,11 @@ func updatePGBackrestInfo(ctx context.Context, c client.Client, pod *corev1.Pod, return nil } } - return errors.New("backup annotations are not found in pgbackrest") + log := logging.FromContext(ctx) + // We should log error here instead of returning it + // to allow deletion of the backup in the Starting/Running state + log.Error(nil, "backup annotations are not found in pgbackrest") + return nil } func finishBackup(ctx context.Context, c client.Client, pgBackup *v2.PerconaPGBackup, job *batchv1.Job) (*reconcile.Result, error) { diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 5a32bc090d..8ba1ee9ef4 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -1,6 +1,3 @@ -//go:build envtest -// +build envtest - package pgcluster import ( @@ -17,8 +14,10 @@ import ( "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace/noop" appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" @@ -1808,3 +1807,461 @@ var _ = Describe("CR Validations", Ordered, func() { }) }) }) + +var _ = Describe("Init Container", Ordered, func() { + ctx := context.Background() + + const crName = "init-container-test" + const ns = crName + crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName, + Namespace: ns, + }, + } + + BeforeAll(func() { + By("Creating the Namespace to perform the tests") + err := k8sClient.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the Namespace to perform the tests") + _ = k8sClient.Delete(ctx, namespace) + }) + + cr, err := readDefaultCR(crName, ns) + It("should read defautl cr.yaml", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + It("should create PerconaPGCluster", func() { + status := cr.Status + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + cr.Status = status + Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) + }) + + It("Controller should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + It("should create fake pods for statefulsets", func() { + stsList := &appsv1.StatefulSetList{} + Expect(k8sClient.List(ctx, stsList, client.InNamespace(ns))).To(Succeed()) + Expect(len(stsList.Items)).To(Equal(4)) + Expect(createFakePodsForStatefulsets(ctx, k8sClient, stsList)).To(Succeed()) + }) + It("Controller should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + + Context("check init containers", func() { + stsList := &appsv1.StatefulSetList{} + var backupJob batchv1.Job + It("should get statefulsets", func() { + selector, err := naming.AsSelector(metav1.LabelSelector{MatchLabels: map[string]string{naming.LabelCluster: crName, naming.LabelInstanceSet: "instance1"}}) + Expect(err).To(Succeed()) + + Expect(k8sClient.List(ctx, stsList, client.InNamespace(ns), client.MatchingLabelsSelector{Selector: selector})).To(Succeed()) + + Expect(len(stsList.Items)).To(Equal(3)) + }) + It("should get replica-create backup job", func() { + jobList := &batchv1.JobList{} + Expect(k8sClient.List(ctx, jobList, client.InNamespace(ns))).To(Succeed()) + + Expect(len(jobList.Items)).To(Equal(1)) + + backupJob = jobList.Items[0] + }) + + It("should have default init container in the instances", func() { + for _, sts := range stsList.Items { + var initContainer *corev1.Container + for _, c := range sts.Spec.Template.Spec.InitContainers { + if c.Name == "database-init" { + initContainer = &c + break + } + } + Expect(initContainer).NotTo(BeNil()) + + Expect(initContainer.Image).To(Equal("some-image")) + Expect(initContainer.ImagePullPolicy).To(Equal(corev1.PullAlways)) + Expect(initContainer.Command).To(Equal([]string{"/usr/local/bin/init-entrypoint.sh"})) + Expect(initContainer.Resources).To(Equal(corev1.ResourceRequirements{})) + Expect(initContainer.SecurityContext).To(Equal(&corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{ + "ALL", + }, + }, + Privileged: ptr.To(false), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), + AllowPrivilegeEscalation: ptr.To(false), + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + })) + Expect(initContainer.TerminationMessagePath).To(Equal("/dev/termination-log")) + Expect(initContainer.TerminationMessagePolicy).To(Equal(corev1.TerminationMessageReadFile)) + Expect(initContainer.VolumeMounts).To(Equal([]corev1.VolumeMount{ + { + Name: "crunchy-bin", + MountPath: "/opt/crunchy", + }, + { + Name: "tmp", + MountPath: "/tmp", + }, + })) + } + }) + It("should have default init container in the backup job", func() { + var initContainer *corev1.Container + for _, c := range backupJob.Spec.Template.Spec.InitContainers { + if c.Name == "pgbackrest-init" { + initContainer = &c + break + } + } + Expect(initContainer).NotTo(BeNil()) + + Expect(initContainer.Image).To(Equal("some-image")) + Expect(initContainer.ImagePullPolicy).To(Equal(corev1.PullAlways)) + Expect(initContainer.Command).To(Equal([]string{"/usr/local/bin/init-entrypoint.sh"})) + Expect(initContainer.Resources).To(Equal(corev1.ResourceRequirements{})) + Expect(initContainer.SecurityContext).To(Equal(&corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{ + "ALL", + }, + }, + Privileged: ptr.To(false), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), + AllowPrivilegeEscalation: ptr.To(false), + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + })) + Expect(initContainer.TerminationMessagePath).To(Equal("/dev/termination-log")) + Expect(initContainer.TerminationMessagePolicy).To(Equal(corev1.TerminationMessageReadFile)) + Expect(initContainer.VolumeMounts).To(Equal([]corev1.VolumeMount{ + { + Name: "crunchy-bin", + MountPath: "/opt/crunchy", + }, + })) + }) + + It("update global initContainer", func() { + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(cr), cr)).To(Succeed()) + + cr.Spec.InitContainer.Image = "new-image" + cr.Spec.InitContainer.ContainerSecurityContext = &corev1.SecurityContext{ + RunAsNonRoot: ptr.To(false), + } + cr.Spec.InitContainer.Resources = &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + } + Expect(k8sClient.Update(ctx, cr)).Should(Succeed()) + }) + It("should delete backup job labels and annotations", func() { + // Deleting job labels and annotations to update the job during reconcile + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&backupJob), &backupJob)).To(Succeed()) + backupJob.Labels = nil + backupJob.Annotations = nil + Expect(k8sClient.Update(ctx, &backupJob)).To(Succeed()) + }) + It("Controller should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + It("should get statefulsets", func() { + selector, err := naming.AsSelector(metav1.LabelSelector{MatchLabels: map[string]string{naming.LabelCluster: crName, naming.LabelInstanceSet: "instance1"}}) + Expect(err).To(Succeed()) + + Expect(k8sClient.List(ctx, stsList, client.InNamespace(ns), client.MatchingLabelsSelector{Selector: selector})).To(Succeed()) + + Expect(len(stsList.Items)).To(Equal(3)) + }) + It("should get replica-create backup job", func() { + jobList := &batchv1.JobList{} + Expect(k8sClient.List(ctx, jobList, client.InNamespace(ns))).To(Succeed()) + + Expect(len(jobList.Items)).To(Equal(1)) + + backupJob = jobList.Items[0] + }) + + It("should have updated init container in the instances", func() { + for _, sts := range stsList.Items { + var initContainer *corev1.Container + for _, c := range sts.Spec.Template.Spec.InitContainers { + if c.Name == "database-init" { + initContainer = &c + break + } + } + Expect(initContainer).NotTo(BeNil()) + + Expect(initContainer.Image).To(Equal("new-image")) + Expect(initContainer.ImagePullPolicy).To(Equal(corev1.PullAlways)) + Expect(initContainer.Command).To(Equal([]string{"/usr/local/bin/init-entrypoint.sh"})) + Expect(initContainer.Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + })) + Expect(initContainer.SecurityContext).To(Equal(&corev1.SecurityContext{ + RunAsNonRoot: ptr.To(false), + })) + Expect(initContainer.TerminationMessagePath).To(Equal("/dev/termination-log")) + Expect(initContainer.TerminationMessagePolicy).To(Equal(corev1.TerminationMessageReadFile)) + Expect(initContainer.VolumeMounts).To(Equal([]corev1.VolumeMount{ + { + Name: "crunchy-bin", + MountPath: "/opt/crunchy", + }, + { + Name: "tmp", + MountPath: "/tmp", + }, + })) + } + }) + It("should have updated init container in the backup job", func() { + var initContainer *corev1.Container + for _, c := range backupJob.Spec.Template.Spec.InitContainers { + if c.Name == "pgbackrest-init" { + initContainer = &c + break + } + } + Expect(initContainer).NotTo(BeNil()) + + Expect(initContainer.Image).To(Equal("new-image")) + Expect(initContainer.ImagePullPolicy).To(Equal(corev1.PullAlways)) + Expect(initContainer.Command).To(Equal([]string{"/usr/local/bin/init-entrypoint.sh"})) + Expect(initContainer.Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + })) + Expect(initContainer.SecurityContext).To(Equal(&corev1.SecurityContext{ + RunAsNonRoot: ptr.To(false), + })) + Expect(initContainer.TerminationMessagePath).To(Equal("/dev/termination-log")) + Expect(initContainer.TerminationMessagePolicy).To(Equal(corev1.TerminationMessageReadFile)) + Expect(initContainer.VolumeMounts).To(Equal([]corev1.VolumeMount{ + { + Name: "crunchy-bin", + MountPath: "/opt/crunchy", + }, + })) + }) + + It("update initContainer of the instance set", func() { + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(cr), cr)).To(Succeed()) + + cr.Spec.InstanceSets[0].InitContainer = new(v1beta1.InitContainerSpec) + cr.Spec.InstanceSets[0].InitContainer.Image = "instance-image" + cr.Spec.InstanceSets[0].InitContainer.ContainerSecurityContext = &corev1.SecurityContext{ + RunAsNonRoot: ptr.To(true), + } + cr.Spec.InstanceSets[0].InitContainer.Resources = &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("3"), + }, + } + Expect(k8sClient.Update(ctx, cr)).Should(Succeed()) + }) + It("should delete backup job labels and annotations", func() { + // Deleting job labels and annotations to update the job during reconcile + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&backupJob), &backupJob)).To(Succeed()) + backupJob.Labels = nil + backupJob.Annotations = nil + Expect(k8sClient.Update(ctx, &backupJob)).To(Succeed()) + }) + It("Controller should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + It("should get statefulsets", func() { + selector, err := naming.AsSelector(metav1.LabelSelector{MatchLabels: map[string]string{naming.LabelCluster: crName, naming.LabelInstanceSet: "instance1"}}) + Expect(err).To(Succeed()) + + Expect(k8sClient.List(ctx, stsList, client.InNamespace(ns), client.MatchingLabelsSelector{Selector: selector})).To(Succeed()) + + Expect(len(stsList.Items)).To(Equal(3)) + }) + It("should get replica-create backup job", func() { + jobList := &batchv1.JobList{} + Expect(k8sClient.List(ctx, jobList, client.InNamespace(ns))).To(Succeed()) + + Expect(len(jobList.Items)).To(Equal(1)) + + backupJob = jobList.Items[0] + }) + + It("should have updated init container in the instances", func() { + for _, sts := range stsList.Items { + var initContainer *corev1.Container + for _, c := range sts.Spec.Template.Spec.InitContainers { + if c.Name == "database-init" { + initContainer = &c + break + } + } + Expect(initContainer).NotTo(BeNil()) + + Expect(initContainer.Image).To(Equal("instance-image")) + Expect(initContainer.ImagePullPolicy).To(Equal(corev1.PullAlways)) + Expect(initContainer.Command).To(Equal([]string{"/usr/local/bin/init-entrypoint.sh"})) + Expect(initContainer.Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("3"), + }, + })) + Expect(initContainer.SecurityContext).To(Equal(&corev1.SecurityContext{ + RunAsNonRoot: ptr.To(true), + })) + Expect(initContainer.TerminationMessagePath).To(Equal("/dev/termination-log")) + Expect(initContainer.TerminationMessagePolicy).To(Equal(corev1.TerminationMessageReadFile)) + Expect(initContainer.VolumeMounts).To(Equal([]corev1.VolumeMount{ + { + Name: "crunchy-bin", + MountPath: "/opt/crunchy", + }, + { + Name: "tmp", + MountPath: "/tmp", + }, + })) + } + }) + It("should have the same init container in the backup job", func() { + var initContainer *corev1.Container + for _, c := range backupJob.Spec.Template.Spec.InitContainers { + if c.Name == "pgbackrest-init" { + initContainer = &c + break + } + } + Expect(initContainer).NotTo(BeNil()) + + Expect(initContainer.Image).To(Equal("new-image")) + Expect(initContainer.ImagePullPolicy).To(Equal(corev1.PullAlways)) + Expect(initContainer.Command).To(Equal([]string{"/usr/local/bin/init-entrypoint.sh"})) + Expect(initContainer.Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + }, + })) + Expect(initContainer.SecurityContext).To(Equal(&corev1.SecurityContext{ + RunAsNonRoot: ptr.To(false), + })) + Expect(initContainer.TerminationMessagePath).To(Equal("/dev/termination-log")) + Expect(initContainer.TerminationMessagePolicy).To(Equal(corev1.TerminationMessageReadFile)) + Expect(initContainer.VolumeMounts).To(Equal([]corev1.VolumeMount{ + { + Name: "crunchy-bin", + MountPath: "/opt/crunchy", + }, + })) + }) + + It("should delete backup job labels and annotations", func() { + // Deleting job labels and annotations to update the job during reconcile + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&backupJob), &backupJob)).To(Succeed()) + backupJob.Labels = nil + backupJob.Annotations = nil + Expect(k8sClient.Update(ctx, &backupJob)).To(Succeed()) + }) + It("update initContainer of the pgbackrest set", func() { + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(cr), cr)).To(Succeed()) + + cr.Spec.Backups.PGBackRest.InitContainer = new(v1beta1.InitContainerSpec) + cr.Spec.Backups.PGBackRest.InitContainer.Image = "pgbackrest-image" + cr.Spec.Backups.PGBackRest.InitContainer.ContainerSecurityContext = &corev1.SecurityContext{ + RunAsNonRoot: ptr.To(false), + Privileged: ptr.To(true), + } + cr.Spec.Backups.PGBackRest.InitContainer.Resources = &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("4"), + }, + } + Expect(k8sClient.Update(ctx, cr)).Should(Succeed()) + }) + It("Controller should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + It("should get replica-create backup job", func() { + jobList := &batchv1.JobList{} + Expect(k8sClient.List(ctx, jobList, client.InNamespace(ns))).To(Succeed()) + + Expect(len(jobList.Items)).To(Equal(1)) + + backupJob = jobList.Items[0] + }) + + It("should have updated init container in the backup job", func() { + var initContainer *corev1.Container + for _, c := range backupJob.Spec.Template.Spec.InitContainers { + if c.Name == "pgbackrest-init" { + initContainer = &c + break + } + } + Expect(initContainer).NotTo(BeNil()) + + Expect(initContainer.Image).To(Equal("pgbackrest-image")) + Expect(initContainer.ImagePullPolicy).To(Equal(corev1.PullAlways)) + Expect(initContainer.Command).To(Equal([]string{"/usr/local/bin/init-entrypoint.sh"})) + Expect(initContainer.Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("4"), + }, + })) + Expect(initContainer.SecurityContext).To(Equal(&corev1.SecurityContext{ + Privileged: ptr.To(true), + RunAsNonRoot: ptr.To(false), + })) + Expect(initContainer.TerminationMessagePath).To(Equal("/dev/termination-log")) + Expect(initContainer.TerminationMessagePolicy).To(Equal(corev1.TerminationMessageReadFile)) + Expect(initContainer.VolumeMounts).To(Equal([]corev1.VolumeMount{ + { + Name: "crunchy-bin", + MountPath: "/opt/crunchy", + }, + })) + }) + }) +}) From 1e421a512116bc001f1e3218d26b0caa49d21b67 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Fri, 4 Jul 2025 22:12:29 +0300 Subject: [PATCH 071/300] K8SPG-675 add missing resources.requests options (#1211) --- deploy/cr.yaml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 7f22bfe97f..a229d0d683 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -16,6 +16,9 @@ spec: # limits: # cpu: 2.0 # memory: 4Gi +# requests: +# cpu: 1.0 +# memory: 3Gi # containerSecurityContext: # runAsUser: 1001 # runAsGroup: 1001 @@ -216,12 +219,18 @@ spec: # limits: # cpu: 2.0 # memory: 4Gi +# requests: +# cpu: 1.0 +# memory: 3Gi # containers: # replicaCertCopy: # resources: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 100m +# memory: 120Mi # sidecars: # - name: testcontainer # image: busybox:latest @@ -301,12 +310,18 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # containers: # pgbouncerConfig: # resources: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # # expose: # annotations: @@ -386,6 +401,9 @@ spec: # limits: # cpu: 2.0 # memory: 4Gi +# requests: +# cpu: 1.0 +# memory: 3Gi # containerSecurityContext: # runAsUser: 1001 # runAsGroup: 1001 @@ -412,11 +430,17 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # pgbackrestConfig: # resources: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # # configuration: # - secret: @@ -430,6 +454,9 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # tolerations: # - effect: NoSchedule # key: role @@ -470,6 +497,9 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: @@ -559,6 +589,13 @@ spec: # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service +# resources: +# limits: +# memory: 200M +# cpu: 350m +# requests: +# memory: 150M +# cpu: 300m # customClusterName: "" # postgresParams: "" # querySource: pgstatmonitor From 899025a7d837a7c625e84c2dc969edcb482d9cfd Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Fri, 4 Jul 2025 22:12:29 +0300 Subject: [PATCH 072/300] K8SPG-675 add missing resources.requests options (#1211) --- deploy/cr.yaml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 7f22bfe97f..a229d0d683 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -16,6 +16,9 @@ spec: # limits: # cpu: 2.0 # memory: 4Gi +# requests: +# cpu: 1.0 +# memory: 3Gi # containerSecurityContext: # runAsUser: 1001 # runAsGroup: 1001 @@ -216,12 +219,18 @@ spec: # limits: # cpu: 2.0 # memory: 4Gi +# requests: +# cpu: 1.0 +# memory: 3Gi # containers: # replicaCertCopy: # resources: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 100m +# memory: 120Mi # sidecars: # - name: testcontainer # image: busybox:latest @@ -301,12 +310,18 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # containers: # pgbouncerConfig: # resources: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # # expose: # annotations: @@ -386,6 +401,9 @@ spec: # limits: # cpu: 2.0 # memory: 4Gi +# requests: +# cpu: 1.0 +# memory: 3Gi # containerSecurityContext: # runAsUser: 1001 # runAsGroup: 1001 @@ -412,11 +430,17 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # pgbackrestConfig: # resources: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # # configuration: # - secret: @@ -430,6 +454,9 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi # tolerations: # - effect: NoSchedule # key: role @@ -470,6 +497,9 @@ spec: # limits: # cpu: 200m # memory: 128Mi +# requests: +# cpu: 150m +# memory: 120Mi affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: @@ -559,6 +589,13 @@ spec: # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service +# resources: +# limits: +# memory: 200M +# cpu: 350m +# requests: +# memory: 150M +# cpu: 300m # customClusterName: "" # postgresParams: "" # querySource: pgstatmonitor From dd453e4913fb6b97f2bb2673a749711c3d46aae3 Mon Sep 17 00:00:00 2001 From: Valmira Nogueira Date: Fri, 4 Jul 2025 17:58:47 -0300 Subject: [PATCH 073/300] Fix comments --- .../pgvector-extension/01-create-cluster.yaml | 1 - ...erify-pgvector-extension-is-disabled.yaml} | 10 +-- .../tests/pgvector-extension/03-assert.yaml | 88 ------------------- .../03-enable-pgvector-extension.yaml | 13 +++ ...-verify-pgvector-extension-is-enabled.yaml | 34 +++++++ ...aml => 05-disable-pgvector-extension.yaml} | 0 ...erify-pgvector-extension-is-disabled.yaml} | 2 - 7 files changed, 48 insertions(+), 100 deletions(-) rename e2e-tests/tests/pgvector-extension/{02-verify-pgvector-extension-is-enabled.yaml => 02-verify-pgvector-extension-is-disabled.yaml} (55%) delete mode 100644 e2e-tests/tests/pgvector-extension/03-assert.yaml create mode 100644 e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml create mode 100644 e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml rename e2e-tests/tests/pgvector-extension/{03-disable-pgvector-extension.yaml => 05-disable-pgvector-extension.yaml} (100%) rename e2e-tests/tests/pgvector-extension/{04-verify-pgvector-extension-is-disabled.yaml => 06-verify-pgvector-extension-is-disabled.yaml} (95%) diff --git a/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml b/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml index bf7276223f..4764045e8a 100644 --- a/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml +++ b/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml @@ -9,5 +9,4 @@ commands: source ../../functions get_cr "pgvector-extension" ${RANDOM} \ - | yq '.spec.extensions.builtin.pgvector=true' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-enabled.yaml b/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-disabled.yaml similarity index 55% rename from e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-enabled.yaml rename to e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-disabled.yaml index 0dd633eb61..e23df8ea45 100644 --- a/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-enabled.yaml +++ b/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-disabled.yaml @@ -12,15 +12,7 @@ commands: "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") if [[ "$result" = *"vector"* ]]; then - echo "pgvector extension is enabled" - else - echo "pgvector extension is not enabled" + echo "pgvector extension is not disabled by default" exit 1 fi - - echo "Testing extension" - run_psql_local \ - "SELECT '\''[1,2,3]'\''::vector <-> '\''[3,2,1]'\''::vector;" \ - "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres" - timeout: 360 diff --git a/e2e-tests/tests/pgvector-extension/03-assert.yaml b/e2e-tests/tests/pgvector-extension/03-assert.yaml deleted file mode 100644 index 903a1768da..0000000000 --- a/e2e-tests/tests/pgvector-extension/03-assert.yaml +++ /dev/null @@ -1,88 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 300 ---- -kind: StatefulSet -apiVersion: apps/v1 -metadata: - labels: - postgres-operator.crunchydata.com/cluster: pgvector-extension - postgres-operator.crunchydata.com/data: postgres - postgres-operator.crunchydata.com/instance-set: instance1 - ownerReferences: - - apiVersion: postgres-operator.crunchydata.com/v1beta1 - kind: PostgresCluster - name: pgvector-extension - controller: true - blockOwnerDeletion: true -status: - observedGeneration: 1 - replicas: 1 - readyReplicas: 1 - updatedReplicas: 1 - collisionCount: 0 ---- -kind: Deployment -apiVersion: apps/v1 -metadata: - name: pgvector-extension-pgbouncer - labels: - postgres-operator.crunchydata.com/cluster: pgvector-extension - postgres-operator.crunchydata.com/role: pgbouncer - annotations: - deployment.kubernetes.io/revision: '1' - ownerReferences: - - apiVersion: postgres-operator.crunchydata.com/v1beta1 - kind: PostgresCluster - name: pgvector-extension - controller: true - blockOwnerDeletion: true -status: - observedGeneration: 1 - replicas: 3 - updatedReplicas: 3 - readyReplicas: 3 ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: pgvector-extension - ownerReferences: - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGCluster - name: pgvector-extension - controller: true - blockOwnerDeletion: true - finalizers: - - postgres-operator.crunchydata.com/finalizer -spec: - backups: - pgbackrest: {} -status: - instances: - - name: instance1 - readyReplicas: 3 - replicas: 3 - updatedReplicas: 3 - observedGeneration: 1 - proxy: - pgBouncer: - readyReplicas: 3 - replicas: 3 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: pgvector-extension -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready diff --git a/e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml b/e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml new file mode 100644 index 0000000000..bf7276223f --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "pgvector-extension" ${RANDOM} \ + | yq '.spec.extensions.builtin.pgvector=true' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml b/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml new file mode 100644 index 0000000000..c8187eff0e --- /dev/null +++ b/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml @@ -0,0 +1,34 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + retries=10 + wait_seconds=5 + + for i in $(seq 1 $retries); do + + result=$(run_psql_local \ + "SELECT * FROM pg_extension WHERE extname = '\''vector'\'';" \ + "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") + + if [[ "$result" = *"vector"* ]]; then + echo "pgvector extension is enabled, verifying extension" + run_psql_local \ + "SELECT '\''[1,2,3]'\''::vector <-> '\''[3,2,1]'\''::vector;" \ + "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres" + + exit 0 + fi + + echo "pgvector extension not enabled, retrying in $wait_seconds seconds..." + sleep $wait_seconds + done + + echo "pgvector extension is not properly enabled" + exit 1 + timeout: 360 diff --git a/e2e-tests/tests/pgvector-extension/03-disable-pgvector-extension.yaml b/e2e-tests/tests/pgvector-extension/05-disable-pgvector-extension.yaml similarity index 100% rename from e2e-tests/tests/pgvector-extension/03-disable-pgvector-extension.yaml rename to e2e-tests/tests/pgvector-extension/05-disable-pgvector-extension.yaml diff --git a/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-disabled.yaml b/e2e-tests/tests/pgvector-extension/06-verify-pgvector-extension-is-disabled.yaml similarity index 95% rename from e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-disabled.yaml rename to e2e-tests/tests/pgvector-extension/06-verify-pgvector-extension-is-disabled.yaml index dc61e541b0..ed129a6032 100644 --- a/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-disabled.yaml +++ b/e2e-tests/tests/pgvector-extension/06-verify-pgvector-extension-is-disabled.yaml @@ -11,8 +11,6 @@ commands: wait_seconds=5 for i in $(seq 1 $retries); do - echo "Attempt $i of $retries..." - result=$(run_psql_local \ "SELECT * FROM pg_extension WHERE extname = '\''vector'\'';" \ "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") From 5968723495e1cda8a29abbbdc6156d9e1752cb01 Mon Sep 17 00:00:00 2001 From: Valmira Nogueira Date: Fri, 4 Jul 2025 18:11:04 -0300 Subject: [PATCH 074/300] Add test to files that trigger test execution --- e2e-tests/run-minikube.csv | 1 + e2e-tests/run-pr.csv | 1 + e2e-tests/run-release.csv | 1 + 3 files changed, 3 insertions(+) diff --git a/e2e-tests/run-minikube.csv b/e2e-tests/run-minikube.csv index 0e95f7f03b..a2384e6573 100644 --- a/e2e-tests/run-minikube.csv +++ b/e2e-tests/run-minikube.csv @@ -4,6 +4,7 @@ custom-tls demand-backup finalizers init-deploy +pgvector-extension one-pod operator-self-healing scaling diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index e8c8d96f05..2535ebccaf 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -8,6 +8,7 @@ monitoring monitoring-pmm3 one-pod operator-self-healing +pgvector-extension pitr scaling scheduled-backup diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 55e8d44061..c0fe5431d1 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -10,6 +10,7 @@ monitoring monitoring-pmm3 one-pod operator-self-healing +pgvector-extension pitr scaling scheduled-backup From 08da68cfdcef5838c38b56d370abc4b4ec7680ba Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Mon, 7 Jul 2025 19:49:11 +0300 Subject: [PATCH 075/300] K8SPG-730: add `.status.observedGeneration` for PerconaPGCluster (#1199) https://perconadev.atlassian.net/browse/K8SPG-730 Co-authored-by: Viacheslav Sarzhan --- .../generated/pgv2.percona.com_perconapgclusters.yaml | 3 +++ config/crd/bases/pgv2.percona.com_perconapgclusters.yaml | 3 +++ deploy/bundle.yaml | 3 +++ deploy/crd.yaml | 3 +++ deploy/cw-bundle.yaml | 3 +++ percona/controller/pgcluster/status.go | 2 ++ percona/controller/pgcluster/status_test.go | 6 ++++++ pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go | 7 ++++++- 8 files changed, 29 insertions(+), 1 deletion(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 050e83ca42..e703e64e87 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -18345,6 +18345,9 @@ spec: items: type: string type: array + observedGeneration: + format: int64 + type: integer patroniVersion: type: string pgbouncer: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 871e89b05e..74eb55aac7 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -18752,6 +18752,9 @@ spec: items: type: string type: array + observedGeneration: + format: int64 + type: integer patroniVersion: type: string pgbouncer: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index f2531bfc34..f796491aa9 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -19049,6 +19049,9 @@ spec: items: type: string type: array + observedGeneration: + format: int64 + type: integer patroniVersion: type: string pgbouncer: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index ed6416046b..479d957f68 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -19049,6 +19049,9 @@ spec: items: type: string type: array + observedGeneration: + format: int64 + type: integer patroniVersion: type: string pgbouncer: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index be92efa6b7..bf832d78a9 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -19049,6 +19049,9 @@ spec: items: type: string type: array + observedGeneration: + format: int64 + type: integer patroniVersion: type: string pgbouncer: diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index 238155cc2b..4222d8dbd6 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -122,6 +122,8 @@ func (r *PGClusterReconciler) updateStatus(ctx context.Context, cr *v2.PerconaPG cluster.Status.State = r.getState(cr, &cluster.Status, status) + cluster.Status.ObservedGeneration = cluster.Generation + updateConditions(cluster, status) return r.Client.Status().Update(ctx, cluster) diff --git a/percona/controller/pgcluster/status_test.go b/percona/controller/pgcluster/status_test.go index 7a8c3f88c7..2b08dc7c0a 100644 --- a/percona/controller/pgcluster/status_test.go +++ b/percona/controller/pgcluster/status_test.go @@ -93,6 +93,7 @@ var _ = Describe("PG Cluster status", Ordered, func() { Expect(cr.Status.Postgres.Ready).Should(Equal(int32(3))) Expect(cr.Status.Postgres.Size).Should(Equal(int32(4))) Expect(cr.Status.Postgres.InstanceSets).Should(HaveLen(2)) + Expect(cr.Status.ObservedGeneration).Should(Equal(int64(1))) Expect(cr.Status.Postgres.InstanceSets).Should(ContainElement(gs.MatchFields(gs.IgnoreExtras, gs.Fields{ "Name": Equal("instance1"), "Ready": Equal(int32(0)), @@ -138,6 +139,7 @@ var _ = Describe("PG Cluster status", Ordered, func() { return err == nil }, time.Second*15, time.Millisecond*250).Should(BeTrue()) + Expect(cr.Status.ObservedGeneration).Should(Equal(int64(1))) Expect(cr.Status.PGBouncer.Ready).Should(Equal(int32(0))) Expect(cr.Status.PGBouncer.Size).Should(Equal(int32(1))) }) @@ -294,6 +296,7 @@ var _ = Describe("PG Cluster status", Ordered, func() { return err == nil }, time.Second*15, time.Millisecond*250).Should(BeTrue()) Expect(cr.Status.Host).Should(Equal(pgBouncerSVC.Name + "." + ns + ".svc")) + Expect(cr.Status.ObservedGeneration).Should(Equal(int64(2))) }) }) @@ -330,6 +333,8 @@ var _ = Describe("PG Cluster status", Ordered, func() { return err == nil }, time.Second*15, time.Millisecond*250).Should(BeTrue()) Expect(cr.Status.Host).Should(Equal("22.22.22.22")) + + Expect(cr.Status.ObservedGeneration).Should(Equal(int64(3))) }) }) }) @@ -393,6 +398,7 @@ var _ = Describe("PG Cluster status", Ordered, func() { condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) Expect(condition.Status).Should(Equal(metav1.ConditionFalse)) + Expect(cr.Status.ObservedGeneration).Should(Equal(int64(1))) }) }) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index a63503c4f8..d2d5198b4e 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -457,6 +457,10 @@ type PerconaPGClusterStatus struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=status Conditions []metav1.Condition `json:"conditions,omitempty"` + + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status + ObservedGeneration int64 `json:"observedGeneration,omitempty"` } type Backups struct { @@ -823,7 +827,8 @@ func (p PGInstanceSetSpec) ToCrunchy() crunchyv1beta1.PostgresInstanceSetSpec { VolumeMounts: p.VolumeMounts, SecurityContext: p.SecurityContext, TablespaceVolumes: p.TablespaceVolumes, - InitContainer: p.InitContainer} + InitContainer: p.InitContainer, + } } type ServiceExpose struct { From 92d1256deff148e528b8f3a71355465765d1245b Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Mon, 7 Jul 2025 16:40:48 -0300 Subject: [PATCH 076/300] K8SPG-818 Update versions for 2.7.0 release (#1213) * K8SPG-818 Update versions for 2.7.0 release * Fix pg17 image tag --- Makefile | 14 ++--- config/bundle/kustomization.yaml | 4 +- config/cw-bundle/kustomization.yaml | 4 +- config/manager/cluster/kustomization.yaml | 4 +- config/manager/namespace/kustomization.yaml | 4 +- deploy/bundle.yaml | 2 +- deploy/cr.yaml | 12 ++-- deploy/cw-bundle.yaml | 2 +- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 +-- e2e-tests/functions | 2 +- e2e-tests/release_versions | 70 ++++++++++----------- 13 files changed, 65 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index 472bc36f27..e0f98390fd 100644 --- a/Makefile +++ b/Makefile @@ -425,17 +425,17 @@ include e2e-tests/release_versions release: generate $(SED) -i \ -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(VERSION)/}" \ - -e "/^spec:/,/^ image:/{s#image: .*#image: $(IMAGE_POSTGRESQL16)#}" \ - -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(IMAGE_PGBOUNCER16)#}" \ - -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(IMAGE_PGBACKREST16)#}" \ + -e "/^spec:/,/^ image:/{s#image: .*#image: $(IMAGE_POSTGRESQL17)#}" \ + -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(IMAGE_PGBOUNCER17)#}" \ + -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(IMAGE_BACKREST17)#}" \ -e "/extensions:/,/image:/{s#image: .*#image: $(IMAGE_OPERATOR)#}" \ - -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(IMAGE_PMM_CLIENT)#}" deploy/cr.yaml + -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(IMAGE_PMM3_CLIENT)#}" deploy/cr.yaml $(SED) -i -r "/Version *= \"[0-9]+\.[0-9]+\.[0-9]+\"$$/ s/[0-9]+\.[0-9]+\.[0-9]+/$(VERSION)/" pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go $(SED) -i \ -e "/^spec:/,/^ image:/{s#image: .*#image: $(IMAGE_OPERATOR)#}" \ - -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(IMAGE_POSTGRESQL16)#}" \ - -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(IMAGE_PGBOUNCER16)#}" \ - -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(IMAGE_PGBACKREST16)#}" deploy/upgrade.yaml + -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(IMAGE_POSTGRESQL17)#}" \ + -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(IMAGE_PGBOUNCER17)#}" \ + -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(IMAGE_BACKREST17)#}" deploy/upgrade.yaml # Prepare main branch after release MAJOR_VER := $(shell grep -oE "crVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+\.[0-9]+\.[0-9]+"|cut -d'.' -f1) diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index a803332017..1f1bca6817 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -6,5 +6,5 @@ resources: - ../manager/namespace images: - name: postgres-operator - newName: perconalab/percona-postgresql-operator - newTag: main + newName: percona/percona-postgresql-operator + newTag: 2.7.0 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 164176a224..2e58fb5dbc 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -7,5 +7,5 @@ resources: images: - name: postgres-operator - newName: perconalab/percona-postgresql-operator - newTag: main + newName: percona/percona-postgresql-operator + newTag: 2.7.0 diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index f5eedfb3e1..46b272f528 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -8,5 +8,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: perconalab/percona-postgresql-operator - newTag: main + newName: percona/percona-postgresql-operator + newTag: 2.7.0 diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 721fe3093d..274e45ceee 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -9,5 +9,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: perconalab/percona-postgresql-operator - newTag: main + newName: percona/percona-postgresql-operator + newTag: 2.7.0 diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index f2531bfc34..036569b9b5 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -47581,7 +47581,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: perconalab/percona-postgresql-operator:main + image: percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index a229d0d683..abab194bb2 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -11,7 +11,7 @@ metadata: spec: crVersion: 2.7.0 # initContainer: -# image: perconalab/percona-postgresql-operator:main +# image: percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: perconalab/percona-postgresql-operator:main-ppg17-postgres + image: percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -304,7 +304,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: perconalab/percona-postgresql-operator:main-pgbouncer17 + image: percona/percona-pgbouncer:1.24.1 # exposeSuperusers: true # resources: # limits: @@ -394,7 +394,7 @@ spec: pgbackrest: # metadata: # labels: - image: perconalab/percona-postgresql-operator:main-pgbackrest17 + image: percona/percona-pgbackrest:2.55.0 # initContainer: # image: perconalab/percona-postgresql-operator:main # resources: @@ -585,7 +585,7 @@ spec: pmm: enabled: false - image: perconalab/pmm-client:dev-latest + image: percona/pmm-client:3.2.0 # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -619,7 +619,7 @@ spec: # - basebackup # extensions: -# image: perconalab/percona-postgresql-operator:main +# image: percona/percona-postgresql-operator:2.7.0 # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index be92efa6b7..a9ffe36c0f 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -47579,7 +47579,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: perconalab/percona-postgresql-operator:main + image: percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 90232d8f7d..481d2a7d19 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: perconalab/percona-postgresql-operator:main + image: percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 24e1f7081e..263b13c814 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: perconalab/percona-postgresql-operator:main + image: percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index d5a275bf49..59bc769d91 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-15-to-16 spec: postgresClusterName: cluster1 - image: perconalab/percona-postgresql-operator:main-upgrade + image: percona/percona-postgresql-operator:2.7.0-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: perconalab/percona-postgresql-operator:main-ppg17-postgres - toPgBouncerImage: perconalab/percona-postgresql-operator:main-pgbouncer17 - toPgBackRestImage: perconalab/percona-postgresql-operator:main-pgbackrest17 + toPostgresImage: percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres + toPgBouncerImage: percona/percona-pgbouncer:1.24.1 + toPgBackRestImage: percona/percona-pgbackrest:2.55.0 diff --git a/e2e-tests/functions b/e2e-tests/functions index 0a28f8fe0e..a12ef9b6c8 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -2,7 +2,7 @@ # set root repo relatively to a test dir ROOT_REPO=${ROOT_REPO:-$(realpath ../../..)} -CERT_MANAGER_VER="1.17.1" +CERT_MANAGER_VER="1.18.2" test_name=$(basename "$(pwd)") source "${ROOT_REPO}/e2e-tests/vars.sh" diff --git a/e2e-tests/release_versions b/e2e-tests/release_versions index 1bb96ab1a1..80d860d66e 100644 --- a/e2e-tests/release_versions +++ b/e2e-tests/release_versions @@ -1,45 +1,45 @@ # Images versions -IMAGE_OPERATOR=percona/percona-postgresql-operator:2.6.0 +IMAGE_OPERATOR=percona/percona-postgresql-operator:2.7.0 -IMAGE_POSTGRESQL17=percona/percona-postgresql-operator:2.6.0-ppg17.2-postgres -IMAGE_PGBOUNCER17=percona/percona-postgresql-operator:2.6.0-ppg17.2-pgbouncer1.23.1 -IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.6.0-ppg17.2-postgres-gis3.3.7 -IMAGE_BACKREST17=percona/percona-postgresql-operator:2.6.0-ppg17.2-pgbackrest2.54.0 +IMAGE_POSTGRESQL17=percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres +IMAGE_PGBOUNCER17=percona/percona-pgbouncer:1.24.1 +IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres-gis3.3.8 +IMAGE_BACKREST17=percona/percona-pgbackrest:2.55.0 -IMAGE_POSTGRESQL16=percona/percona-postgresql-operator:2.6.0-ppg16.8-postgres -IMAGE_PGBOUNCER16=percona/percona-postgresql-operator:2.6.0-ppg16.8-pgbouncer1.24.0 -IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.6.0-ppg16.8-postgres-gis3.3.8 -IMAGE_BACKREST16=percona/percona-postgresql-operator:2.6.0-ppg16.8-pgbackrest2.54.2 +IMAGE_POSTGRESQL16=percona/percona-postgresql-operator:2.7.0-ppg16.9-postgres +IMAGE_PGBOUNCER16=percona/percona-pgbouncer:1.24.1 +IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.7.0-ppg16.9-postgres-gis3.3.8 +IMAGE_BACKREST16=percona/percona-pgbackrest:2.55.0 -IMAGE_POSTGRESQL15=percona/percona-postgresql-operator:2.6.0-ppg15.12-postgres -IMAGE_PGBOUNCER15=percona/percona-postgresql-operator:2.6.0-ppg15.12-pgbouncer1.24.0 -IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.6.0-ppg15.12-postgres-gis3.3.8 -IMAGE_BACKREST15=percona/percona-postgresql-operator:2.6.0-ppg15.12-pgbackrest2.54.2 +IMAGE_POSTGRESQL15=percona/percona-postgresql-operator:2.7.0-ppg15.13-postgres +IMAGE_PGBOUNCER15=percona/percona-pgbouncer:1.24.1 +IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.7.0-ppg15.13-postgres-gis3.3.8 +IMAGE_BACKREST15=percona/percona-pgbackrest:2.55.0 -IMAGE_POSTGRESQL14=percona/percona-postgresql-operator:2.6.0-ppg14.17-postgres -IMAGE_PGBOUNCER14=percona/percona-postgresql-operator:2.6.0-ppg14.17-pgbouncer1.24.0 -IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.6.0-ppg14.17-postgres-gis3.3.8 -IMAGE_BACKREST14=percona/percona-postgresql-operator:2.6.0-ppg14.17-pgbackrest2.54.2 +IMAGE_POSTGRESQL14=percona/percona-postgresql-operator:2.7.0-ppg14.18-postgres +IMAGE_PGBOUNCER14=percona/percona-pgbouncer:1.24.1 +IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.7.0-ppg14.18-postgres-gis3.3.8 +IMAGE_BACKREST14=percona/percona-pgbackrest:2.55.0 -IMAGE_POSTGRESQL13=percona/percona-postgresql-operator:2.6.0-ppg13.20-postgres -IMAGE_PGBOUNCER13=percona/percona-postgresql-operator:2.6.0-ppg13.20-pgbouncer1.24.0 -IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.6.0-ppg13.20-postgres-gis3.3.8 -IMAGE_BACKREST13=percona/percona-postgresql-operator:2.6.0-ppg13.20-pgbackrest2.54.2 +IMAGE_POSTGRESQL13=percona/percona-postgresql-operator:2.7.0-ppg13.21-postgres +IMAGE_PGBOUNCER13=percona/percona-pgbouncer:1.24.1 +IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.7.0-ppg13.21-postgres-gis3.3.8 +IMAGE_BACKREST13=percona/percona-pgbackrest:2.55.0 -IMAGE_UPGRADE=percona/percona-postgresql-operator:2.6.0-upgrade +IMAGE_UPGRADE=percona/percona-postgresql-operator:2.7.0-upgrade -IMAGE_PMM_CLIENT=percona/pmm-client:2.44.0 -IMAGE_PMM_SERVER=percona/pmm-server:2.44.0 -IMAGE_PMM3_CLIENT=percona/pmm-client:3.1.0 -IMAGE_PMM3_SERVER=percona/pmm-server:3.1.0 +IMAGE_PMM_CLIENT=percona/pmm-client:2.44.1 +IMAGE_PMM_SERVER=percona/pmm-server:2.44.1 +IMAGE_PMM3_CLIENT=percona/pmm-client:3.2.0 +IMAGE_PMM3_SERVER=percona/pmm-server:3.2.0 # Supported k8s versions -GKE_MIN=1.29 -GKE_MAX=1.31 -EKS_MIN=1.29 -EKS_MAX=1.32 -AKS_MIN=1.29 -AKS_MAX=1.31 -OPENSHIFT_MIN=4.14.48 -OPENSHIFT_MAX=4.17.19 -MINIKUBE_MAX=1.32.0 \ No newline at end of file +GKE_MIN=1.30 +GKE_MAX=1.32 +EKS_MIN=1.30 +EKS_MAX=1.33 +AKS_MIN=1.30 +AKS_MAX=1.32 +OPENSHIFT_MIN=4.15.53 +OPENSHIFT_MAX=4.19.2 +MINIKUBE_MAX=1.33.1 \ No newline at end of file From 65f6d198eb9d0f3e11343489bb3635cd0bcdc84d Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 8 Jul 2025 09:54:13 +0300 Subject: [PATCH 077/300] K8SPG-752 support loadBalancerClass (#1200) * K8SPG-752 support loadBalancerClass * improve unit test to include load balancer configs --------- Co-authored-by: Viacheslav Sarzhan --- ...ator.crunchydata.com_postgresclusters.yaml | 32 ++ .../pgv2.percona.com_perconapgclusters.yaml | 24 ++ .../pgv2.percona.com_perconapgclusters.yaml | 24 ++ ...ator.crunchydata.com_postgresclusters.yaml | 32 ++ deploy/bundle.yaml | 56 ++++ deploy/cr.yaml | 3 + deploy/crd.yaml | 56 ++++ deploy/cw-bundle.yaml | 56 ++++ .../v2/perconapgcluster_types.go | 34 ++- .../v2/perconapgcluster_types_test.go | 279 ++++++++++++++++++ .../v2/zz_generated.deepcopy.go | 5 + .../v1beta1/shared_types.go | 8 + .../v1beta1/zz_generated.deepcopy.go | 5 + 13 files changed, 604 insertions(+), 10 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index afb2a25a8c..27c0f750b3 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -18038,6 +18038,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -18382,6 +18390,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -18434,6 +18450,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -20126,6 +20150,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index e703e64e87..fd4317efe5 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -8227,6 +8227,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -8263,6 +8271,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -15936,6 +15952,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 74eb55aac7..a0dccc91bf 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -8634,6 +8634,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -8670,6 +8678,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -16343,6 +16359,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 881887b0ec..e209c9206d 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -17947,6 +17947,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -18291,6 +18299,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -18343,6 +18359,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -20024,6 +20048,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index f796491aa9..5ec0a7101f 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -8931,6 +8931,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -8967,6 +8975,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -16640,6 +16656,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44464,6 +44488,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44808,6 +44840,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44860,6 +44900,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -46541,6 +46589,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. diff --git a/deploy/cr.yaml b/deploy/cr.yaml index a229d0d683..5f4cffe8b3 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -165,6 +165,7 @@ spec: # labels: # my-label: value2 # type: LoadBalancer +# loadBalancerClass: "eks.amazonaws.com/nlb" # loadBalancerSourceRanges: # - 10.0.0.0/8 # exposeReplicas: @@ -173,6 +174,7 @@ spec: # labels: # my-label: value2 # type: LoadBalancer +# loadBalancerClass: "eks.amazonaws.com/nlb" # loadBalancerSourceRanges: # - 10.0.0.0/8 @@ -329,6 +331,7 @@ spec: # labels: # my-label: value2 # type: LoadBalancer +# loadBalancerClass: "eks.amazonaws.com/nlb" # loadBalancerSourceRanges: # - 10.0.0.0/8 # diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 479d957f68..407ac4d2d9 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -8931,6 +8931,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -8967,6 +8975,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -16640,6 +16656,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44464,6 +44488,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44808,6 +44840,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44860,6 +44900,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -46541,6 +46589,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index bf832d78a9..0e0dc91efb 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -8931,6 +8931,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -8967,6 +8975,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -16640,6 +16656,14 @@ spec: additionalProperties: type: string type: object + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44464,6 +44488,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44808,6 +44840,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -44860,6 +44900,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. @@ -46541,6 +46589,14 @@ spec: - Cluster - Local type: string + loadBalancerClass: + description: |- + LoadBalancerClass specifies the class of the load balancer implementation + to be used. This field is supported for Service Type LoadBalancer only. + + More info: + https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + type: string loadBalancerSourceRanges: description: |- LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index d2d5198b4e..dd579c5d4d 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -304,8 +304,8 @@ func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crun postgresCluster.Spec.Paused = cr.Spec.Unmanaged postgresCluster.Spec.Shutdown = cr.Spec.Pause postgresCluster.Spec.Standby = cr.Spec.Standby - postgresCluster.Spec.Service = cr.Spec.Expose.ToCrunchy() - postgresCluster.Spec.ReplicaService = cr.Spec.ExposeReplicas.ToCrunchy() + postgresCluster.Spec.Service = cr.Spec.Expose.ToCrunchy(cr.Spec.CRVersion) + postgresCluster.Spec.ReplicaService = cr.Spec.ExposeReplicas.ToCrunchy(cr.Spec.CRVersion) postgresCluster.Spec.CustomReplicationClientTLSSecret = cr.Spec.Secrets.CustomReplicationClientTLSSecret postgresCluster.Spec.CustomTLSSecret = cr.Spec.Secrets.CustomTLSSecret @@ -365,7 +365,7 @@ func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crun postgresCluster.Spec.Users = users postgresCluster.Spec.InstanceSets = cr.Spec.InstanceSets.ToCrunchy() - postgresCluster.Spec.Proxy = cr.Spec.Proxy.ToCrunchy() + postgresCluster.Spec.Proxy = cr.Spec.Proxy.ToCrunchy(cr.Spec.CRVersion) postgresCluster.Spec.Extensions.PGStatMonitor = *cr.Spec.Extensions.BuiltIn.PGStatMonitor postgresCluster.Spec.Extensions.PGStatStatements = *cr.Spec.Extensions.BuiltIn.PGStatStatements @@ -395,7 +395,6 @@ const ( AppStatePaused AppState = "paused" AppStateStopping AppState = "stopping" AppStateReady AppState = "ready" - AppStateError AppState = "error" ) type PostgresInstanceSetStatus struct { @@ -848,18 +847,26 @@ type ServiceExpose struct { // +kubebuilder:validation:Enum={ClusterIP,NodePort,LoadBalancer} Type string `json:"type,omitempty"` + // LoadBalancerClass specifies the class of the load balancer implementation + // to be used. This field is supported for Service Type LoadBalancer only. + // + // More info: + // https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + // +optional + LoadBalancerClass *string `json:"loadBalancerClass,omitempty"` + // LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. // This field will be ignored if the cloud-provider does not support the feature. // +optional LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"` } -func (s *ServiceExpose) ToCrunchy() *crunchyv1beta1.ServiceSpec { +func (s *ServiceExpose) ToCrunchy(version string) *crunchyv1beta1.ServiceSpec { if s == nil { return nil } - return &crunchyv1beta1.ServiceSpec{ + serviceSpec := &crunchyv1beta1.ServiceSpec{ Metadata: &crunchyv1beta1.Metadata{ Annotations: s.Annotations, Labels: s.Labels, @@ -868,6 +875,13 @@ func (s *ServiceExpose) ToCrunchy() *crunchyv1beta1.ServiceSpec { Type: s.Type, LoadBalancerSourceRanges: s.LoadBalancerSourceRanges, } + + currVersion, err := gover.NewVersion(version) + if err == nil && currVersion.GreaterThanOrEqual(gover.Must(gover.NewVersion("2.8.0"))) { + serviceSpec.LoadBalancerClass = s.LoadBalancerClass + } + + return serviceSpec } type PGProxySpec struct { @@ -875,13 +889,13 @@ type PGProxySpec struct { PGBouncer *PGBouncerSpec `json:"pgBouncer"` } -func (p *PGProxySpec) ToCrunchy() *crunchyv1beta1.PostgresProxySpec { +func (p *PGProxySpec) ToCrunchy(version string) *crunchyv1beta1.PostgresProxySpec { if p == nil { return nil } return &crunchyv1beta1.PostgresProxySpec{ - PGBouncer: p.PGBouncer.ToCrunchy(), + PGBouncer: p.PGBouncer.ToCrunchy(version), } } @@ -981,7 +995,7 @@ type PGBouncerSpec struct { SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` } -func (p *PGBouncerSpec) ToCrunchy() *crunchyv1beta1.PGBouncerPodSpec { +func (p *PGBouncerSpec) ToCrunchy(version string) *crunchyv1beta1.PGBouncerPodSpec { if p == nil { return nil } @@ -1000,7 +1014,7 @@ func (p *PGBouncerSpec) ToCrunchy() *crunchyv1beta1.PGBouncerPodSpec { Replicas: p.Replicas, MinAvailable: p.MinAvailable, Resources: p.Resources, - Service: p.ServiceExpose.ToCrunchy(), + Service: p.ServiceExpose.ToCrunchy(version), Tolerations: p.Tolerations, TopologySpreadConstraints: p.TopologySpreadConstraints, SecurityContext: p.SecurityContext, diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go index 228056957a..fa43445019 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go @@ -1,11 +1,19 @@ package v2 import ( + "context" "fmt" "os" "testing" + "github.com/stretchr/testify/require" "gotest.tools/v3/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "github.com/percona/percona-postgresql-operator/internal/naming" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPerconaPGCluster_Default(t *testing.T) { @@ -101,3 +109,274 @@ func TestPerconaPGCluster_PostgresImage(t *testing.T) { }) } } + +func TestPerconaPGCluster_ToCrunchy(t *testing.T) { + scheme := runtime.NewScheme() + err := corev1.AddToScheme(scheme) + require.NoError(t, err) + err = crunchyv1beta1.AddToScheme(scheme) + require.NoError(t, err) + err = AddToScheme(scheme) + require.NoError(t, err) + + ctx := context.Background() + + tests := map[string]struct { + name string + expectedPerconaPGCluster *PerconaPGCluster + inputPostgresCluster *crunchyv1beta1.PostgresCluster + expectedError bool + assertClusterFunc func(t *testing.T, actual *crunchyv1beta1.PostgresCluster, expected *PerconaPGCluster) + }{ + "creates new PostgresCluster when nil input": { + expectedPerconaPGCluster: &PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Spec: PerconaPGClusterSpec{ + CRVersion: "2.8.0", + PostgresVersion: 15, + Expose: &ServiceExpose{ + Type: "LoadBalancer", + LoadBalancerClass: &[]string{"someloadbalancerclass"}[0], + }, + ExposeReplicas: &ServiceExpose{ + Type: "LoadBalancer", + LoadBalancerClass: &[]string{"someloadbalancerclass"}[0], + }, + InstanceSets: PGInstanceSets{ + { + Name: "instance1", + Replicas: &[]int32{1}[0], + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + }, + }, + }, + Backups: Backups{ + PGBackRest: PGBackRestArchive{ + Repos: []crunchyv1beta1.PGBackRestRepo{ + {Name: "repo1"}, + }, + }, + }, + }, + }, + assertClusterFunc: func(t *testing.T, actual *crunchyv1beta1.PostgresCluster, expected *PerconaPGCluster) { + assert.Equal(t, actual.Name, expected.Name) + assert.Equal(t, actual.Namespace, expected.Namespace) + assert.DeepEqual(t, actual.Finalizers, []string{naming.Finalizer}) + assert.Equal(t, actual.Spec.PostgresVersion, expected.Spec.PostgresVersion) + assert.Equal(t, actual.Labels[LabelOperatorVersion], expected.Spec.CRVersion) + assert.Equal(t, len(actual.Spec.InstanceSets), 1) + assert.Equal(t, len(actual.Spec.InstanceSets), len(expected.Spec.InstanceSets)) + assert.Equal(t, actual.Spec.InstanceSets[0].Name, expected.Spec.InstanceSets[0].Name) + + assert.Equal(t, actual.Spec.Service.Type, expected.Spec.Expose.Type) + assert.Assert(t, actual.Spec.Service.LoadBalancerClass != nil) + assert.Equal(t, actual.Spec.Service.LoadBalancerClass, expected.Spec.Expose.LoadBalancerClass) + + assert.Equal(t, actual.Spec.ReplicaService.Type, expected.Spec.ExposeReplicas.Type) + assert.Assert(t, actual.Spec.ReplicaService.LoadBalancerClass != nil) + assert.Equal(t, actual.Spec.ReplicaService.LoadBalancerClass, expected.Spec.ExposeReplicas.LoadBalancerClass) + }, + }, + "updates existing PostgresCluster": { + expectedPerconaPGCluster: &PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + Labels: map[string]string{ + "test-label": "test-value", + }, + Annotations: map[string]string{ + "test-annotation": "test-value", + }, + }, + Spec: PerconaPGClusterSpec{ + CRVersion: "2.5.0", + PostgresVersion: 14, + Port: &[]int32{5432}[0], + TLSOnly: true, + InstanceSets: PGInstanceSets{ + { + Name: "instance1", + Replicas: &[]int32{2}[0], + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + }, + }, + }, + Backups: Backups{ + PGBackRest: PGBackRestArchive{ + Repos: []crunchyv1beta1.PGBackRestRepo{ + {Name: "repo1"}, + }, + }, + }, + }, + }, + inputPostgresCluster: &crunchyv1beta1.PostgresCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "existing-cluster", + Namespace: "test-namespace", + }, + }, + assertClusterFunc: func(t *testing.T, actual *crunchyv1beta1.PostgresCluster, expected *PerconaPGCluster) { + assert.Equal(t, actual.Spec.PostgresVersion, expected.Spec.PostgresVersion) + assert.Equal(t, actual.Spec.Port, expected.Spec.Port) + assert.Equal(t, actual.Spec.TLSOnly, expected.Spec.TLSOnly) + assert.Equal(t, actual.Labels["test-label"], "test-value") + assert.Equal(t, actual.Labels[LabelOperatorVersion], expected.Spec.CRVersion) + }, + }, + "handles PMM enabled scenario": { + expectedPerconaPGCluster: &PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Spec: PerconaPGClusterSpec{ + CRVersion: "2.5.0", + PostgresVersion: 15, + PMM: &PMMSpec{ + Enabled: true, + QuerySource: PgStatStatements, + }, + InstanceSets: PGInstanceSets{ + { + Name: "instance1", + Replicas: &[]int32{1}[0], + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + }, + }, + }, + Backups: Backups{ + PGBackRest: PGBackRestArchive{ + Repos: []crunchyv1beta1.PGBackRestRepo{ + {Name: "repo1"}, + }, + }, + }, + }, + }, + assertClusterFunc: func(t *testing.T, actual *crunchyv1beta1.PostgresCluster, _ *PerconaPGCluster) { + hasMonitoringUser := false + for _, user := range actual.Spec.Users { + if user.Name == UserMonitoring { + hasMonitoringUser = true + break + } + } + assert.Equal(t, hasMonitoringUser, true) + }, + }, + "handles AutoCreateUserSchema annotation": { + expectedPerconaPGCluster: &PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Spec: PerconaPGClusterSpec{ + CRVersion: "2.5.0", + PostgresVersion: 15, + AutoCreateUserSchema: &[]bool{true}[0], + InstanceSets: PGInstanceSets{ + { + Name: "instance1", + Replicas: &[]int32{1}[0], + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + }, + }, + }, + Backups: Backups{ + PGBackRest: PGBackRestArchive{ + Repos: []crunchyv1beta1.PGBackRestRepo{ + {Name: "repo1"}, + }, + }, + }, + }, + }, + assertClusterFunc: func(t *testing.T, actual *crunchyv1beta1.PostgresCluster, _ *PerconaPGCluster) { + assert.Equal(t, actual.Annotations[naming.AutoCreateUserSchemaAnnotation], "true") + }, + }, + "filters out reserved monitoring user": { + expectedPerconaPGCluster: &PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Spec: PerconaPGClusterSpec{ + CRVersion: "2.5.0", + PostgresVersion: 15, + Users: []crunchyv1beta1.PostgresUserSpec{ + {Name: "regular-user"}, + {Name: UserMonitoring}, + {Name: "another-user"}, + }, + InstanceSets: PGInstanceSets{ + { + Name: "instance1", + Replicas: &[]int32{1}[0], + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + }, + }, + }, + Backups: Backups{ + PGBackRest: PGBackRestArchive{ + Repos: []crunchyv1beta1.PGBackRestRepo{ + {Name: "repo1"}, + }, + }, + }, + }, + }, + assertClusterFunc: func(t *testing.T, result *crunchyv1beta1.PostgresCluster, original *PerconaPGCluster) { + assert.Equal(t, len(result.Spec.Users), 2) + userNames := make([]string, len(result.Spec.Users)) + for i, user := range result.Spec.Users { + userNames[i] = string(user.Name) + } + assert.Assert(t, contains(userNames, "regular-user")) + assert.Assert(t, contains(userNames, "another-user")) + assert.Assert(t, !contains(userNames, UserMonitoring)) + }, + }, + } + + for testName, tt := range tests { + t.Run(testName, func(t *testing.T) { + tt.expectedPerconaPGCluster.Default() + + crunchyCluster, err := tt.expectedPerconaPGCluster.ToCrunchy(ctx, tt.inputPostgresCluster, scheme) + + if tt.expectedError { + assert.Assert(t, err != nil) + return + } + + assert.NilError(t, err) + assert.Assert(t, crunchyCluster != nil) + + if tt.assertClusterFunc != nil { + tt.assertClusterFunc(t, crunchyCluster, tt.expectedPerconaPGCluster) + } + }) + } +} + +// Helper function to check if a slice contains a string +func contains(slice []string, item string) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index 8a0f75ebb0..8a0de11fa1 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -1121,6 +1121,11 @@ func (in *ServiceExpose) DeepCopyInto(out *ServiceExpose) { *out = new(int32) **out = **in } + if in.LoadBalancerClass != nil { + in, out := &in.LoadBalancerClass, &out.LoadBalancerClass + *out = new(string) + **out = **in + } if in.LoadBalancerSourceRanges != nil { in, out := &in.LoadBalancerSourceRanges, &out.LoadBalancerSourceRanges *out = make([]string, len(*in)) diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go index 0561d897aa..9176596d15 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go @@ -40,6 +40,14 @@ type ServiceSpec struct { // +kubebuilder:validation:Enum={ClusterIP,NodePort,LoadBalancer} Type string `json:"type"` + // LoadBalancerClass specifies the class of the load balancer implementation + // to be used. This field is supported for Service Type LoadBalancer only. + // + // More info: + // https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + // +optional + LoadBalancerClass *string `json:"loadBalancerClass,omitempty"` + // LoadBalancerSourceRanges is a list of IP CIDRs allowed access to load. // This field will be ignored if the cloud-provider does not support the feature. // +optional diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 5e3b4b8671..99765c4df8 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -2328,6 +2328,11 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { *out = new(int32) **out = **in } + if in.LoadBalancerClass != nil { + in, out := &in.LoadBalancerClass, &out.LoadBalancerClass + *out = new(string) + **out = **in + } if in.LoadBalancerSourceRanges != nil { in, out := &in.LoadBalancerSourceRanges, &out.LoadBalancerSourceRanges *out = make([]string, len(*in)) From ed35964e3d7dea6c023d74c6d62a5e07c348ec6a Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 8 Jul 2025 10:39:25 +0300 Subject: [PATCH 078/300] K8SPG-624 Add support for Using S3ForcePathStyle / verifyTLS customExtensions --- .../pgv2.percona.com_perconapgclusters.yaml | 4 ++ build/postgres-operator/install-extensions.sh | 2 + cmd/extension-installer/main.go | 10 +++-- .../pgv2.percona.com_perconapgclusters.yaml | 4 ++ deploy/bundle.yaml | 4 ++ deploy/cr.yaml | 18 +++++---- deploy/crd.yaml | 4 ++ deploy/cw-bundle.yaml | 4 ++ percona/controller/pgcluster/controller.go | 6 +-- percona/controller/pgupgrade/controller.go | 6 +-- percona/extensions/{k8s.go => containers.go} | 37 ++++++++++--------- percona/extensions/s3.go | 7 +++- percona/extensions/storage.go | 4 +- .../v2/perconapgcluster_types.go | 12 +++--- 14 files changed, 77 insertions(+), 45 deletions(-) rename percona/extensions/{k8s.go => containers.go} (71%) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index fd4317efe5..91966db202 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -8340,8 +8340,12 @@ spec: properties: bucket: type: string + disableSSL: + type: string endpoint: type: string + forcePathStyle: + type: string region: type: string secret: diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index 6a8555bd78..082e135799 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -9,6 +9,8 @@ declare -a args=( -type "${STORAGE_TYPE}" -region "${STORAGE_REGION}" -bucket "${STORAGE_BUCKET}" + -force-path-style "${STORAGE_FORCE_PATH_STYLE}" + -disable-ssl "${STORAGE_DISABLE_SSL}" -extension-path "${PGDATA_EXTENSIONS}" ) diff --git a/cmd/extension-installer/main.go b/cmd/extension-installer/main.go index 5045e608eb..7919f943ab 100644 --- a/cmd/extension-installer/main.go +++ b/cmd/extension-installer/main.go @@ -12,7 +12,7 @@ import ( func main() { var storageType, endpoint, region, bucket, key, extensionPath string - var install, uninstall bool + var install, uninstall, forcePathStyle, disableSSL bool flag.StringVar(&storageType, "type", "", "Storage type") flag.StringVar(&endpoint, "endpoint", "", "Storage endpoint") @@ -23,6 +23,8 @@ func main() { flag.BoolVar(&install, "install", false, "Install extension") flag.BoolVar(&uninstall, "uninstall", false, "Uninstall extension") + flag.BoolVar(&forcePathStyle, "forcePathStyle", false, "Force path style") + flag.BoolVar(&disableSSL, "disableSSL", false, "Disable SSL") flag.Parse() if (install && uninstall) || (!install && !uninstall) { @@ -31,7 +33,7 @@ func main() { log.Printf("starting extension installer for %s/%s (%s) in %s", bucket, key, storageType, region) - storage := initStorage(extensions.StorageType(storageType), endpoint, bucket, region) + storage := initStorage(extensions.StorageType(storageType), endpoint, bucket, region, forcePathStyle, disableSSL) packageName := key + ".tar.gz" @@ -70,10 +72,10 @@ func main() { } } -func initStorage(storageType extensions.StorageType, endpoint, bucket, region string) extensions.ObjectGetter { +func initStorage(storageType extensions.StorageType, endpoint, bucket, region string, s3ForcePathStyle, disableSSL bool) extensions.ObjectGetter { switch storageType { case extensions.StorageTypeS3: - return extensions.NewS3(endpoint, region, bucket) + return extensions.NewS3(endpoint, region, bucket, s3ForcePathStyle, disableSSL) default: log.Fatalf("unknown storage type: %s", os.Getenv("STORAGE_TYPE")) } diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index a0dccc91bf..882ca6883d 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -8747,8 +8747,12 @@ spec: properties: bucket: type: string + disableSSL: + type: string endpoint: type: string + forcePathStyle: + type: string region: type: string secret: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 5ec0a7101f..ae21792b14 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -9044,8 +9044,12 @@ spec: properties: bucket: type: string + disableSSL: + type: string endpoint: type: string + forcePathStyle: + type: string region: type: string secret: diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 5f4cffe8b3..d7851f4a5d 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -621,14 +621,16 @@ spec: # - pgbackrest # - basebackup -# extensions: -# image: perconalab/percona-postgresql-operator:main -# imagePullPolicy: Always -# storage: -# type: s3 -# bucket: pg-extensions -# region: eu-central-1 -# endpoint: s3.eu-central-1.amazonaws.com + extensions: + image: perconalab/percona-postgresql-operator:main + imagePullPolicy: Always + storage: + type: s3 + bucket: pg-extensions + region: eu-central-1 + endpoint: s3.eu-central-1.amazonaws.com + forcePathStyle: false + disableSSL: false # secret: # name: cluster1-extensions-secret # builtin: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 407ac4d2d9..9127130294 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -9044,8 +9044,12 @@ spec: properties: bucket: type: string + disableSSL: + type: string endpoint: type: string + forcePathStyle: + type: string region: type: string secret: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 0e0dc91efb..149df41fff 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -9044,8 +9044,12 @@ spec: properties: bucket: type: string + disableSSL: + type: string endpoint: type: string + forcePathStyle: + type: string region: type: string secret: diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index f3e0d03928..480570a6d1 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -806,17 +806,17 @@ func (r *PGClusterReconciler) reconcileCustomExtensions(ctx context.Context, cr for i := 0; i < len(cr.Spec.InstanceSets); i++ { set := &cr.Spec.InstanceSets[i] - set.InitContainers = append(set.InitContainers, extensions.ExtensionRelocatorContainer( + set.InitContainers = append(set.InitContainers, extensions.RelocatorContainer( cr, cr.PostgresImage(), cr.Spec.ImagePullPolicy, cr.Spec.PostgresVersion, )) - set.InitContainers = append(set.InitContainers, extensions.ExtensionInstallerContainer( + set.InitContainers = append(set.InitContainers, extensions.InstallerContainer( cr, cr.Spec.PostgresVersion, &cr.Spec.Extensions, strings.Join(extensionKeys, ","), cr.Spec.OpenShift, )) - set.VolumeMounts = append(set.VolumeMounts, extensions.ExtensionVolumeMounts(cr.Spec.PostgresVersion)...) + set.VolumeMounts = append(set.VolumeMounts, extensions.VolumeMounts(cr.Spec.PostgresVersion)...) } return nil } diff --git a/percona/controller/pgupgrade/controller.go b/percona/controller/pgupgrade/controller.go index 4a53ce64d6..1f82b929fc 100644 --- a/percona/controller/pgupgrade/controller.go +++ b/percona/controller/pgupgrade/controller.go @@ -180,11 +180,11 @@ func (r *PGUpgradeReconciler) createPGUpgrade(ctx context.Context, cluster *pgv2 extensionKeys = append(extensionKeys, key) } - pgUpgrade.Spec.InitContainers = append(pgUpgrade.Spec.InitContainers, extensions.ExtensionRelocatorContainer( + pgUpgrade.Spec.InitContainers = append(pgUpgrade.Spec.InitContainers, extensions.RelocatorContainer( cluster, *perconaPGUpgrade.Spec.Image, cluster.Spec.ImagePullPolicy, pgVersion, )) - pgUpgrade.Spec.InitContainers = append(pgUpgrade.Spec.InitContainers, extensions.ExtensionInstallerContainer( + pgUpgrade.Spec.InitContainers = append(pgUpgrade.Spec.InitContainers, extensions.InstallerContainer( cluster, pgVersion, &cluster.Spec.Extensions, @@ -194,7 +194,7 @@ func (r *PGUpgradeReconciler) createPGUpgrade(ctx context.Context, cluster *pgv2 } // we're only adding the volume mounts for target version since current volume mounts are already mounted - pgUpgrade.Spec.VolumeMounts = append(pgUpgrade.Spec.VolumeMounts, extensions.ExtensionVolumeMounts( + pgUpgrade.Spec.VolumeMounts = append(pgUpgrade.Spec.VolumeMounts, extensions.VolumeMounts( perconaPGUpgrade.Spec.ToPostgresVersion)..., ) diff --git a/percona/extensions/k8s.go b/percona/extensions/containers.go similarity index 71% rename from percona/extensions/k8s.go rename to percona/extensions/containers.go index 7cf5839ae5..f88733bf41 100644 --- a/percona/extensions/k8s.go +++ b/percona/extensions/containers.go @@ -13,16 +13,11 @@ func GetExtensionKey(pgMajor int, name, version string) string { return fmt.Sprintf("%s-pg%d-%s", name, pgMajor, version) } -// ExtensionRelocatorContainer returns a container that will relocate extensions from the base image (i.e. pg_stat_monitor, pg_audit) +// RelocatorContainer returns a container that will relocate extensions from the base image (i.e. pg_stat_monitor, pg_audit) // to the data directory so we don't lose them when user adds a custom extension. -func ExtensionRelocatorContainer(cr *pgv2.PerconaPGCluster, image string, imagePullPolicy corev1.PullPolicy, postgresVersion int) corev1.Container { - containerName := "extension-relocator" - if cr.CompareVersion("2.4.0") >= 0 { - containerName = fmt.Sprintf("extension-relocator-%d", postgresVersion) - } - +func RelocatorContainer(_ *pgv2.PerconaPGCluster, image string, imagePullPolicy corev1.PullPolicy, postgresVersion int) corev1.Container { return corev1.Container{ - Name: containerName, + Name: fmt.Sprintf("extension-relocator-%d", postgresVersion), Image: image, ImagePullPolicy: imagePullPolicy, Command: []string{"/usr/local/bin/relocate-extensions.sh"}, @@ -41,22 +36,17 @@ func ExtensionRelocatorContainer(cr *pgv2.PerconaPGCluster, image string, imageP } } -func ExtensionInstallerContainer(cr *pgv2.PerconaPGCluster, postgresVersion int, spec *pgv2.ExtensionsSpec, extensions string, openshift *bool) corev1.Container { +func InstallerContainer(cr *pgv2.PerconaPGCluster, postgresVersion int, spec *pgv2.ExtensionsSpec, extensions string, openshift *bool) corev1.Container { mounts := []corev1.VolumeMount{ { Name: "postgres-data", MountPath: "/pgdata", }, } - mounts = append(mounts, ExtensionVolumeMounts(postgresVersion)...) - - containerName := "extension-installer" - if cr.CompareVersion("2.4.0") >= 0 { - containerName = fmt.Sprintf("extension-installer-%d", postgresVersion) - } + mounts = append(mounts, VolumeMounts(postgresVersion)...) container := corev1.Container{ - Name: containerName, + Name: fmt.Sprintf("extension-installer-%d", postgresVersion), Image: spec.Image, ImagePullPolicy: spec.ImagePullPolicy, Command: []string{"/usr/local/bin/install-extensions.sh"}, @@ -100,6 +90,19 @@ func ExtensionInstallerContainer(cr *pgv2.PerconaPGCluster, postgresVersion int, VolumeMounts: mounts, } + if cr.CompareVersion("2.8.0") >= 0 { + container.Env = append(container.Env, []corev1.EnvVar{ + { + Name: "STORAGE_DISABLE_SSL", + Value: spec.Storage.DisableSSL, + }, + { + Name: "STORAGE_FORCE_PATH_STYLE", + Value: spec.Storage.ForcePathStyle, + }, + }...) + } + if openshift == nil || !*openshift { container.SecurityContext = &corev1.SecurityContext{ RunAsUser: func() *int64 { @@ -112,7 +115,7 @@ func ExtensionInstallerContainer(cr *pgv2.PerconaPGCluster, postgresVersion int, return container } -func ExtensionVolumeMounts(postgresVersion int) []corev1.VolumeMount { +func VolumeMounts(postgresVersion int) []corev1.VolumeMount { return []corev1.VolumeMount{ { Name: "postgres-data", diff --git a/percona/extensions/s3.go b/percona/extensions/s3.go index 0106a7f393..4c1d4ed376 100644 --- a/percona/extensions/s3.go +++ b/percona/extensions/s3.go @@ -15,8 +15,11 @@ type S3 struct { svc *s3.S3 } -func NewS3(endpoint, region, bucket string) *S3 { - cfg := aws.NewConfig().WithRegion(region) +func NewS3(endpoint, region, bucket string, s3ForcePathStyle, disableSSL bool) *S3 { + cfg := aws.NewConfig(). + WithRegion(region). + WithDisableSSL(disableSSL). + WithS3ForcePathStyle(s3ForcePathStyle) if endpoint != "" { cfg = cfg.WithEndpoint(endpoint) diff --git a/percona/extensions/storage.go b/percona/extensions/storage.go index 190aa3fb53..b3279fdf95 100644 --- a/percona/extensions/storage.go +++ b/percona/extensions/storage.go @@ -12,7 +12,5 @@ type ObjectGetter interface { type StorageType string const ( - StorageTypeS3 StorageType = "s3" - StorageTypeGCS StorageType = "gcs" - StorageTypeAzure StorageType = "azure" + StorageTypeS3 StorageType = "s3" ) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index dd579c5d4d..46c937e70e 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -628,11 +628,13 @@ type CustomExtensionSpec struct { type CustomExtensionsStorageSpec struct { // +kubebuilder:validation:Enum={s3,gcs,azure} - Type string `json:"type,omitempty"` - Bucket string `json:"bucket,omitempty"` - Region string `json:"region,omitempty"` - Endpoint string `json:"endpoint,omitempty"` - Secret *corev1.SecretProjection `json:"secret,omitempty"` + Type string `json:"type,omitempty"` + Bucket string `json:"bucket,omitempty"` + Region string `json:"region,omitempty"` + Endpoint string `json:"endpoint,omitempty"` + ForcePathStyle string `json:"forcePathStyle,omitempty"` + DisableSSL string `json:"disableSSL,omitempty"` + Secret *corev1.SecretProjection `json:"secret,omitempty"` } type BuiltInExtensionsSpec struct { From c9a63b38cf796e865df197e862d957ec80352a27 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 8 Jul 2025 11:22:52 +0300 Subject: [PATCH 079/300] Update build/postgres-operator/install-extensions.sh Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- build/postgres-operator/install-extensions.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index 082e135799..4a9e706977 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -9,8 +9,8 @@ declare -a args=( -type "${STORAGE_TYPE}" -region "${STORAGE_REGION}" -bucket "${STORAGE_BUCKET}" - -force-path-style "${STORAGE_FORCE_PATH_STYLE}" - -disable-ssl "${STORAGE_DISABLE_SSL}" + -force-path-style "${STORAGE_FORCE_PATH_STYLE}" + -disable-ssl "${STORAGE_DISABLE_SSL}" -extension-path "${PGDATA_EXTENSIONS}" ) From d667fecb5c1f3d44c409972d0981d8c3d15bce24 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 8 Jul 2025 11:23:34 +0300 Subject: [PATCH 080/300] disable cr extensions --- deploy/cr.yaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index d7851f4a5d..a02a23da84 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -621,16 +621,16 @@ spec: # - pgbackrest # - basebackup - extensions: - image: perconalab/percona-postgresql-operator:main - imagePullPolicy: Always - storage: - type: s3 - bucket: pg-extensions - region: eu-central-1 - endpoint: s3.eu-central-1.amazonaws.com - forcePathStyle: false - disableSSL: false +# extensions: +# image: perconalab/percona-postgresql-operator:main +# imagePullPolicy: Always +# storage: +# type: s3 +# bucket: pg-extensions +# region: eu-central-1 +# endpoint: s3.eu-central-1.amazonaws.com +# forcePathStyle: false +# disableSSL: false # secret: # name: cluster1-extensions-secret # builtin: From 245b6e586f1fadd89ea1e46515070e1c3e552ffe Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 8 Jul 2025 16:14:43 +0300 Subject: [PATCH 081/300] fix params for extension installer --- cmd/extension-installer/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/extension-installer/main.go b/cmd/extension-installer/main.go index 7919f943ab..4275e49b3e 100644 --- a/cmd/extension-installer/main.go +++ b/cmd/extension-installer/main.go @@ -23,8 +23,8 @@ func main() { flag.BoolVar(&install, "install", false, "Install extension") flag.BoolVar(&uninstall, "uninstall", false, "Uninstall extension") - flag.BoolVar(&forcePathStyle, "forcePathStyle", false, "Force path style") - flag.BoolVar(&disableSSL, "disableSSL", false, "Disable SSL") + flag.BoolVar(&forcePathStyle, "force-path-style", false, "Force path style") + flag.BoolVar(&disableSSL, "disable-ssl", false, "Disable SSL") flag.Parse() if (install && uninstall) || (!install && !uninstall) { From 7a0551e26a7e3a70ce6be950fdfaa572c3bdb93d Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 8 Jul 2025 16:47:00 +0300 Subject: [PATCH 082/300] handle the missing env vars properly for versions <2.8.0 --- build/postgres-operator/install-extensions.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index 4a9e706977..2acab4ed4e 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -9,8 +9,6 @@ declare -a args=( -type "${STORAGE_TYPE}" -region "${STORAGE_REGION}" -bucket "${STORAGE_BUCKET}" - -force-path-style "${STORAGE_FORCE_PATH_STYLE}" - -disable-ssl "${STORAGE_DISABLE_SSL}" -extension-path "${PGDATA_EXTENSIONS}" ) @@ -18,6 +16,16 @@ if [[ -n $STORAGE_ENDPOINT ]]; then args+=(-endpoint "$STORAGE_ENDPOINT") fi +# Checking the STORAGE_DISABLE_SSL env for backwards compatibility before 2.8.0 +if [[ -n $STORAGE_DISABLE_SSL ]]; then + args+=(-disable-ssl "$STORAGE_ENDPOINT") +fi + +# Checking the STORAGE_FORCE_PATH_STYLE env for backwards compatibility before 2.8.0 +if [[ -n $STORAGE_FORCE_PATH_STYLE ]]; then + args+=(-force-path-style "$STORAGE_FORCE_PATH_STYLE") +fi + for key in "${extensions[@]}"; do if [ -f "${PGDATA_EXTENSIONS}"/"${key}".installed ]; then echo "Extension ${key} already installed" From 9fd4d4d32576fa47fa2af5e43b0529a2f3fc4736 Mon Sep 17 00:00:00 2001 From: Valmira Nogueira Date: Tue, 8 Jul 2025 14:56:18 -0300 Subject: [PATCH 083/300] Add e2e test for database init sql --- e2e-tests/run-minikube.csv | 1 + e2e-tests/run-pr.csv | 1 + e2e-tests/run-release.csv | 1 + .../tests/database-init-sql/00-assert.yaml | 24 +++++ .../database-init-sql/00-deploy-operator.yaml | 13 +++ .../tests/database-init-sql/01-assert.yaml | 12 +++ .../01-init-database-sql-configmap.yaml | 8 ++ .../tests/database-init-sql/02-assert.yaml | 88 +++++++++++++++++++ .../database-init-sql/02-create-cluster.yaml | 14 +++ .../03-verify-database-initialized.yaml | 18 ++++ .../99-remove-cluster-gracefully.yaml | 21 +++++ 11 files changed, 201 insertions(+) create mode 100644 e2e-tests/tests/database-init-sql/00-assert.yaml create mode 100644 e2e-tests/tests/database-init-sql/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/database-init-sql/01-assert.yaml create mode 100644 e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml create mode 100644 e2e-tests/tests/database-init-sql/02-assert.yaml create mode 100644 e2e-tests/tests/database-init-sql/02-create-cluster.yaml create mode 100644 e2e-tests/tests/database-init-sql/03-verify-database-initialized.yaml create mode 100644 e2e-tests/tests/database-init-sql/99-remove-cluster-gracefully.yaml diff --git a/e2e-tests/run-minikube.csv b/e2e-tests/run-minikube.csv index a2384e6573..0a46f447c4 100644 --- a/e2e-tests/run-minikube.csv +++ b/e2e-tests/run-minikube.csv @@ -1,6 +1,7 @@ backup-enable-disable custom-extensions custom-tls +database-init-sql demand-backup finalizers init-deploy diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 2535ebccaf..8c480e198e 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -1,6 +1,7 @@ backup-enable-disable custom-extensions custom-tls +database-init-sql demand-backup finalizers init-deploy diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index c0fe5431d1..acc8858345 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -1,6 +1,7 @@ backup-enable-disable custom-extensions custom-tls +database-init-sql demand-backup finalizers init-deploy diff --git a/e2e-tests/tests/database-init-sql/00-assert.yaml b/e2e-tests/tests/database-init-sql/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/database-init-sql/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/database-init-sql/00-deploy-operator.yaml b/e2e-tests/tests/database-init-sql/00-deploy-operator.yaml new file mode 100644 index 0000000000..1aaca58be2 --- /dev/null +++ b/e2e-tests/tests/database-init-sql/00-deploy-operator.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client diff --git a/e2e-tests/tests/database-init-sql/01-assert.yaml b/e2e-tests/tests/database-init-sql/01-assert.yaml new file mode 100644 index 0000000000..9c0b8e726c --- /dev/null +++ b/e2e-tests/tests/database-init-sql/01-assert.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: init-database-sql +data: + init.sql: | + CREATE TABLE e2e_init_table(id INT PRIMARY KEY); + INSERT INTO e2e_init_table VALUES (42); \ No newline at end of file diff --git a/e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml b/e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml new file mode 100644 index 0000000000..4ac1ef2c91 --- /dev/null +++ b/e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: init-database-sql +data: + init.sql: | + CREATE TABLE e2e_init_table(id INT PRIMARY KEY); + INSERT INTO e2e_init_table VALUES (42); \ No newline at end of file diff --git a/e2e-tests/tests/database-init-sql/02-assert.yaml b/e2e-tests/tests/database-init-sql/02-assert.yaml new file mode 100644 index 0000000000..55d56c521b --- /dev/null +++ b/e2e-tests/tests/database-init-sql/02-assert.yaml @@ -0,0 +1,88 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: database-init-sql + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: database-init-sql + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: database-init-sql-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: database-init-sql + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: database-init-sql + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: database-init-sql + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: database-init-sql + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +spec: + backups: + pgbackrest: {} +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: database-init-sql +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/database-init-sql/02-create-cluster.yaml b/e2e-tests/tests/database-init-sql/02-create-cluster.yaml new file mode 100644 index 0000000000..c427e5bd76 --- /dev/null +++ b/e2e-tests/tests/database-init-sql/02-create-cluster.yaml @@ -0,0 +1,14 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr \ + | yq '.spec.databaseInitSQL.name = "init-database-sql"' \ + | yq '.spec.databaseInitSQL.key = "init.sql"' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/database-init-sql/03-verify-database-initialized.yaml b/e2e-tests/tests/database-init-sql/03-verify-database-initialized.yaml new file mode 100644 index 0000000000..7014a63b58 --- /dev/null +++ b/e2e-tests/tests/database-init-sql/03-verify-database-initialized.yaml @@ -0,0 +1,18 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + result=$(run_psql_local \ + "SELECT id FROM e2e_init_table WHERE id = 42" \ + "postgres:$(get_psql_user_pass database-init-sql-pguser-postgres)@$(get_psql_user_host database-init-sql-pguser-postgres)/postgres") + + if [[ "$result" != *"42"* ]]; then + echo "Database has not been initialized" + exit 1 + fi + timeout: 360 diff --git a/e2e-tests/tests/database-init-sql/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/database-init-sql/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..6eb2ba7c63 --- /dev/null +++ b/e2e-tests/tests/database-init-sql/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: database-init-sql +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: database-init-sql +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 From d203a6c8f3a353224c93be631760143d8deecf0e Mon Sep 17 00:00:00 2001 From: Valmira Nogueira Date: Tue, 8 Jul 2025 14:58:47 -0300 Subject: [PATCH 084/300] Add end of file line --- e2e-tests/tests/database-init-sql/01-assert.yaml | 2 +- .../tests/database-init-sql/01-init-database-sql-configmap.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/tests/database-init-sql/01-assert.yaml b/e2e-tests/tests/database-init-sql/01-assert.yaml index 9c0b8e726c..dd317a34f3 100644 --- a/e2e-tests/tests/database-init-sql/01-assert.yaml +++ b/e2e-tests/tests/database-init-sql/01-assert.yaml @@ -9,4 +9,4 @@ metadata: data: init.sql: | CREATE TABLE e2e_init_table(id INT PRIMARY KEY); - INSERT INTO e2e_init_table VALUES (42); \ No newline at end of file + INSERT INTO e2e_init_table VALUES (42); diff --git a/e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml b/e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml index 4ac1ef2c91..8867b26147 100644 --- a/e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml +++ b/e2e-tests/tests/database-init-sql/01-init-database-sql-configmap.yaml @@ -5,4 +5,4 @@ metadata: data: init.sql: | CREATE TABLE e2e_init_table(id INT PRIMARY KEY); - INSERT INTO e2e_init_table VALUES (42); \ No newline at end of file + INSERT INTO e2e_init_table VALUES (42); From ef7bef9dea5437db7353c1c01aeb55551c1ade17 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Wed, 9 Jul 2025 12:17:20 +0200 Subject: [PATCH 085/300] K8SPG-744 Updated Contributing guide with the steps to build and deploy the Operator (#1208) * K8SPG-744 Updated Contributing guide with the steps to build and deploy the Operator * Updated after the review * Removed stuff that should not be part pf the PR * Update CONTRIBUTING.md Co-authored-by: George Kechagias --------- Co-authored-by: George Kechagias Co-authored-by: Viacheslav Sarzhan --- CONTRIBUTING.md | 82 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e918b9d080..5ea6b09f71 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,10 @@ # Contributing to Percona Operator for PostgreSQL +We welcome contributions to the Percona Operator for PostgreSQL project and we're glad that you would like to become a Percona community member and participate in keeping open source open. For you to help us improve the Operator, please follow the guidelines below. + ## Prerequisites -Before submitting code contributions, you should first complete the following prerequisites. +Before submitting code contributions, complete the following prerequisites first. ### 1. Sign the CLA @@ -16,7 +18,7 @@ Please make sure to read and observe the [Contribution Policy](code-of-conduct.m ### 1. Making a bug report -Improvement and bugfix tasks for Percona's projects are tracked in [Jira](https://jira.percona.com/projects/K8SPG/issues). +We track improvement and bugfix tasks for Percona Operator project in [Jira](https://jira.percona.com/projects/K8SPG/issues). Although not mandatory, it is a good practice to examine already open Jira issues first. For bigger contributions, we suggest creating a Jira issue and discussing it with the engineering team and community before proposing any code changes. @@ -24,10 +26,11 @@ Another good place to discuss Percona's projects with developers and other commu ### 2. Contributing to the source tree -Contributions to the source tree should follow the workflow described below: +Follow the workflow described below: + +1. [Fork the repository on GitHub](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo), clone your fork locally, and then [sync your local fork to upstream](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork). Make sure to always sync your fork with upstream before starting to work on any changes. -1. First, you need to [fork the repository on GitHub](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo), clone your fork locally, and then [sync your local fork to upstream](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork). After that, before starting to work on changes, make sure to always sync your fork with upstream. -2. Create a branch for changes you are planning to make. If there is a Jira ticket related to your contribution, it is recommended to name your branch in the following way: `-`, where the issue number is something like `K8SPG-42`. +2. Create a branch for changes you are planning to make. If there is a Jira ticket related to your contribution, name your branch in the following way: `-`, where the issue number is something like `K8SPG-42`. Create the branch in your local repo as follows: @@ -35,7 +38,7 @@ Contributions to the source tree should follow the workflow described below: $ git checkout -b K8SPG-42-fix-feature-X ``` - When your changes are ready, make a commit, mentioning the Jira issue in the commit message, if any: +3. When your changes are ready, make a commit, mentioning the Jira issue in the commit message, if any: ``` $ git add . @@ -43,13 +46,74 @@ Contributions to the source tree should follow the workflow described below: $ git push -u origin K8SPG-42-fix-feature-X ``` -3. Create a pull request to the main repository on GitHub. -4. When the reviewer makes some comments, address any feedback that comes and update the pull request. -5. When your contribution is accepted, your pull request will be approved and merged to the main branch. +4. Create a pull request to the main repository on GitHub. +5. [Build a custom Operator image based on your changes](#build-a-custom-operator-image) to verify that they work +6. [Update deployment manifests](#update-deployment-manifests) to reflect your changes +7. [Run e2e tests](#run-e2e-tests) to verify your changes are stable and robust. +8. Someone from our team reviews your pull request. When the reviewer makes some comments, address any feedback that comes and update the pull request. +9. When your contribution is accepted, your pull request will be approved and merged to the main branch. + +#### Build a custom Operator image based on your changes + +To build a new Operator image based on your local changes, do the following: + +1. Set the `IMAGE` environment variable to the your image repository and tag. For example: + + ``` + $ export IMAGE=/percona-postgresql-operator: + ``` + + Replace and with your own values. + +2. Build the Docker image and push it to the specified repository: + + ``` + $ make build-docker-image + ``` + +#### Update deployment manifests + +Update the files under the `deploy/` directory to reflect any new fields in the resource API, a new image, etc. The `deploy/` directory contains the CRDs, bundles, and other manifests. + +Run the following command to update deployment manifests: + +``` +$ make generate VERSION= +``` + +`` here is the tag of your built image. + +Next, test your custom changes by deploying the Operator on your Kubernetes cluster. + +First, deploy the Operator: + +``` +$ kubectl apply --server-side -f deploy/bundle.yaml +``` + +Then, deploy a Percona PostgreSQL cluster CRD: + +``` +$ kubectl apply -f deploy/cr.yaml +``` + +#### Run end-to-end tests + +The Operator repository includes a collection of end-to-end (e2e) tests under the `e2e-tests/` directory. You can run these tests on your own Kubernetes cluster to ensure that your changes are robust and stable. + + +To run a specific test by name, use the following command. In the example below, we run the `init-deploy` test: + +``` +$ kubectl kuttl test --config e2e-tests/kuttl.yaml --test "^init-deploy\$" --skip-delete +``` + +Replace `init-deploy` with the name of the test you want to run. ### 3. Contributing to documentation The workflow for documentation is similar, but we store source code for the Percona Operator for PostgreSQL documentation in a [separate repository](https://github.com/percona/k8spg-docs). + See the [Documentation Contribution Guide](https://github.com/percona/k8spg-docs/blob/main/CONTRIBUTING.md) for more information. ### 4. Container images From 25feab6fbb5daa5772708e2c673e28b9b16ce795 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 9 Jul 2025 18:31:45 +0300 Subject: [PATCH 086/300] cr: properly wire disabe ssl with the right env var --- build/postgres-operator/install-extensions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index 2acab4ed4e..2338801a76 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -18,7 +18,7 @@ fi # Checking the STORAGE_DISABLE_SSL env for backwards compatibility before 2.8.0 if [[ -n $STORAGE_DISABLE_SSL ]]; then - args+=(-disable-ssl "$STORAGE_ENDPOINT") + args+=(-disable-ssl "$STORAGE_DISABLE_SSL") fi # Checking the STORAGE_FORCE_PATH_STYLE env for backwards compatibility before 2.8.0 From 1b16cc03589c81e3764aeed5d262e0c5b18a46a0 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 9 Jul 2025 18:56:06 +0300 Subject: [PATCH 087/300] try no boolean --- build/postgres-operator/install-extensions.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index 2338801a76..81e50b538d 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -16,14 +16,12 @@ if [[ -n $STORAGE_ENDPOINT ]]; then args+=(-endpoint "$STORAGE_ENDPOINT") fi -# Checking the STORAGE_DISABLE_SSL env for backwards compatibility before 2.8.0 -if [[ -n $STORAGE_DISABLE_SSL ]]; then - args+=(-disable-ssl "$STORAGE_DISABLE_SSL") +if [[ "${STORAGE_DISABLE_SSL}" == "true" ]]; then + args+=(-disable-ssl) fi -# Checking the STORAGE_FORCE_PATH_STYLE env for backwards compatibility before 2.8.0 -if [[ -n $STORAGE_FORCE_PATH_STYLE ]]; then - args+=(-force-path-style "$STORAGE_FORCE_PATH_STYLE") +if [[ "${STORAGE_FORCE_PATH_STYLE}" == "true" ]]; then + args+=(-force-path-style) fi for key in "${extensions[@]}"; do From 47fcc185b499fa81e4e8cd97306201efb119a759 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 10 Jul 2025 10:21:22 +0300 Subject: [PATCH 088/300] Update build/postgres-operator/install-extensions.sh Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- build/postgres-operator/install-extensions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index 81e50b538d..25326b775a 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -20,7 +20,7 @@ if [[ "${STORAGE_DISABLE_SSL}" == "true" ]]; then args+=(-disable-ssl) fi -if [[ "${STORAGE_FORCE_PATH_STYLE}" == "true" ]]; then +if [[ ${STORAGE_FORCE_PATH_STYLE} == "true" ]]; then args+=(-force-path-style) fi From b04ac5737ccde82e88aba92cfa24389d4115345a Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 10 Jul 2025 10:21:29 +0300 Subject: [PATCH 089/300] Update build/postgres-operator/install-extensions.sh Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- build/postgres-operator/install-extensions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index 25326b775a..ca09efe7cd 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -16,7 +16,7 @@ if [[ -n $STORAGE_ENDPOINT ]]; then args+=(-endpoint "$STORAGE_ENDPOINT") fi -if [[ "${STORAGE_DISABLE_SSL}" == "true" ]]; then +if [[ ${STORAGE_DISABLE_SSL} == "true" ]]; then args+=(-disable-ssl) fi From a5cd0e255706373d2e6a1c1b0aaab6072174ba16 Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Thu, 10 Jul 2025 15:58:37 -0300 Subject: [PATCH 090/300] Fix upgrade resource name --- deploy/upgrade.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 59bc769d91..32deeeecf6 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -1,7 +1,7 @@ apiVersion: pgv2.percona.com/v2 kind: PerconaPGUpgrade metadata: - name: cluster1-15-to-16 + name: cluster1-16-to-17 spec: postgresClusterName: cluster1 image: percona/percona-postgresql-operator:2.7.0-upgrade From 2680f9b262e308004eecfb24a0fd0fa943dedea3 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 10 Jul 2025 22:15:02 +0300 Subject: [PATCH 091/300] add conditionally the env vars if the cr is set --- percona/extensions/containers.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/percona/extensions/containers.go b/percona/extensions/containers.go index f88733bf41..48f6056d11 100644 --- a/percona/extensions/containers.go +++ b/percona/extensions/containers.go @@ -91,16 +91,21 @@ func InstallerContainer(cr *pgv2.PerconaPGCluster, postgresVersion int, spec *pg } if cr.CompareVersion("2.8.0") >= 0 { - container.Env = append(container.Env, []corev1.EnvVar{ - { + // Check whether the configuration exists so that existing e2e tests + // that do not set these values are not affected. + if spec.Storage.DisableSSL != "" { + container.Env = append(container.Env, corev1.EnvVar{ Name: "STORAGE_DISABLE_SSL", Value: spec.Storage.DisableSSL, - }, - { + }) + } + + if spec.Storage.ForcePathStyle != "" { + container.Env = append(container.Env, corev1.EnvVar{ Name: "STORAGE_FORCE_PATH_STYLE", Value: spec.Storage.ForcePathStyle, - }, - }...) + }) + } } if openshift == nil || !*openshift { From d076202bf07b8b9f62c8a8f18861809d318f4db5 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Mon, 14 Jul 2025 11:48:00 +0300 Subject: [PATCH 092/300] add e2e test --- e2e-tests/functions | 100 ++++++++++++- .../custom-extensions/00-deploy-operator.yaml | 2 + .../tests/custom-extensions/02-assert.yaml | 10 +- .../custom-extensions/02-install-pg_cron.yaml | 2 +- .../tests/custom-extensions/05-assert.yaml | 10 +- .../tests/custom-extensions/06-assert.yaml | 10 +- .../tests/custom-extensions/10-assert.yaml | 134 ++++++++++++++++++ .../custom-extensions/10-use-aws-storage.yaml | 20 +++ .../tests/custom-extensions/11-assert.yaml | 80 +++++++++++ .../custom-extensions/11-install-pg_cron.yaml | 14 ++ .../custom-extensions/12-enable-pg_cron.yaml | 13 ++ .../tests/custom-extensions/13-assert.yaml | 13 ++ .../13-check-extensions.yaml | 13 ++ e2e-tests/vars.sh | 1 + 14 files changed, 411 insertions(+), 11 deletions(-) create mode 100644 e2e-tests/tests/custom-extensions/10-assert.yaml create mode 100644 e2e-tests/tests/custom-extensions/10-use-aws-storage.yaml create mode 100644 e2e-tests/tests/custom-extensions/11-assert.yaml create mode 100644 e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml create mode 100644 e2e-tests/tests/custom-extensions/12-enable-pg_cron.yaml create mode 100644 e2e-tests/tests/custom-extensions/13-assert.yaml create mode 100644 e2e-tests/tests/custom-extensions/13-check-extensions.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index 0a28f8fe0e..3a8dddd4cd 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -125,6 +125,56 @@ get_operator_pod() { echo $(kubectl get pods -n "${OPERATOR_NS:-$NAMESPACE}" --selector=app.kubernetes.io/name=percona-postgresql-operator -o jsonpath='{.items[].metadata.name}') } +retry() { + local max=$1 + local delay=$2 + shift 2 # cut delay and max args + local n=1 + + until "$@"; do + if [[ $n -ge $max ]]; then + echo "The command ${*} has failed after $n attempts." + exit 1 + fi + ((n++)) + sleep $delay + done +} + +deploy_minio() { + local access_key + local secret_key + access_key="$(kubectl -n "${NAMESPACE}" get secret minio-secret -o jsonpath='{.data.AWS_ACCESS_KEY_ID}' | base64 -d)" + secret_key="$(kubectl -n "${NAMESPACE}" get secret minio-secret -o jsonpath='{.data.AWS_SECRET_ACCESS_KEY}' | base64 -d)" + + helm uninstall -n "${NAMESPACE}" minio-service || : + helm repo remove minio || : + helm repo add minio https://charts.min.io/ + retry 10 60 helm install minio-service \ + -n "${NAMESPACE}" \ + --version "${MINIO_VER}" \ + --set replicas=1 \ + --set mode=standalone \ + --set resources.requests.memory=256Mi \ + --set rootUser=rootuser \ + --set rootPassword=rootpass123 \ + --set "users[0].accessKey"="$(printf '%q' "$(printf '%q' "$access_key")")" \ + --set "users[0].secretKey"="$(printf '%q' "$(printf '%q' "$secret_key")")" \ + --set "users[0].policy"=consoleAdmin \ + --set service.type=ClusterIP \ + --set configPathmc=/tmp/.minio/ \ + --set persistence.size=2G \ + --set securityContext.enabled=false \ + minio/minio + MINIO_POD=$(kubectl -n "${NAMESPACE}" get pods --selector=release=minio-service -o 'jsonpath={.items[].metadata.name}') + wait_pod $MINIO_POD + + # create bucket + kubectl -n "${NAMESPACE}" run -i --rm aws-cli --image=perconalab/awscli --restart=Never -- \ + bash -c "AWS_ACCESS_KEY_ID='$access_key' AWS_SECRET_ACCESS_KEY='$secret_key' AWS_DEFAULT_REGION=us-east-1 \ + /usr/bin/aws --endpoint-url http://minio-service:9000 s3 mb s3://operator-testing" +} + deploy_s3_secrets() { set +o xtrace printf "[global]\nrepo1-s3-key=%s\nrepo1-s3-key-secret=%s\n" \ @@ -147,6 +197,7 @@ deploy_s3_secrets() { ;; "custom-extensions" | "major-upgrade") kubectl -n "${NAMESPACE}" apply -f "${TESTS_CONFIG_DIR}/cloud-secret.yml" + kubectl -n "${NAMESPACE}" apply -f "${TESTS_CONFIG_DIR}/minio-secret.yml" ;; *) kubectl -n "${NAMESPACE}" create secret generic "${test_name}-pgbackrest-secrets" --from-file=cloud.conf="${TEMP_DIR}/pgbackrest-secret.ini" @@ -229,13 +280,20 @@ get_cr() { .spec.backups.pgbackrest.repos += [{"name":"repo3","azure":{"container":"'$BUCKET'"}}] ' $TEMP_DIR/cr.yaml ;; - "custom-extensions" | "major-upgrade") + "major-upgrade") yq eval -i ' .spec.extensions.image = "'$IMAGE'" | .spec.extensions.imagePullPolicy = "Always" | .spec.extensions.storage = {"type": "s3", "bucket": "pg-extensions", "region": "eu-central-1", "secret": {"name": "aws-s3-secret"}} ' $TEMP_DIR/cr.yaml ;; + "custom-extensions") + yq eval -i ' + .spec.extensions.image = "'$IMAGE'" | + .spec.extensions.imagePullPolicy = "Always" | + .spec.extensions.storage = {"type": "s3", "bucket": "operator-testing", "region": "us-east-1", "endpoint": "http://minio-service:9000", "forcePathStyle": "true", "disableSSL": "true", "secret": {"name": "minio-secret"}} + ' $TEMP_DIR/cr.yaml + ;; esac cat $TEMP_DIR/cr.yaml } @@ -276,12 +334,52 @@ get_psql_user_host() { kubectl -n ${NAMESPACE} get "secret/${secret_name}" --template='{{.data.host | base64decode }}' } +get_aws_access_key() { + local secret_name=${1} + + kubectl -n ${NAMESPACE} get "secret/${secret_name}" --template='{{.data.AWS_SECRET_ACCESS_KEY | base64decode }}' +} + +get_aws_access_key_id() { + local secret_name=${1} + + kubectl -n ${NAMESPACE} get "secret/${secret_name}" --template='{{.data.AWS_ACCESS_KEY_ID | base64decode }}' +} + +get_psql_user_host() { + local secret_name=${1} + + kubectl -n ${NAMESPACE} get "secret/${secret_name}" --template='{{.data.host | base64decode }}' +} get_instance_set_pods() { local instance=${1:-instance1} kubectl get pods -n ${NAMESPACE} --selector postgres-operator.crunchydata.com/instance-set=${instance} -o custom-columns='NAME:.metadata.name' --no-headers } +copy_custom_extensions_form_aws() { + set +o xtrace + + access_key="$(kubectl -n "${NAMESPACE}" get secret minio-secret -o jsonpath='{.data.AWS_ACCESS_KEY_ID}' | base64 -d)" + secret_key="$(kubectl -n "${NAMESPACE}" get secret minio-secret -o jsonpath='{.data.AWS_SECRET_ACCESS_KEY}' | base64 -d)" + + kubectl -n "${NAMESPACE}" run -i --rm aws-cli \ + --image=perconalab/awscli \ + --restart=Never -- \ + bash -c " + AWS_ACCESS_KEY_ID=$(get_aws_access_key_id aws-s3-secret) \ + AWS_SECRET_ACCESS_KEY=$(get_aws_access_key aws-s3-secret) \ + AWS_DEFAULT_REGION=eu-central-1 \ + /usr/bin/aws --endpoint-url https://s3.amazonaws.com s3 cp s3://pg-extensions/ /tmp/ --recursive && + + AWS_ACCESS_KEY_ID='${access_key}' \ + AWS_SECRET_ACCESS_KEY='${secret_key}' \ + AWS_DEFAULT_REGION=us-east-1 \ + /usr/bin/aws --endpoint-url http://minio-service:9000 s3 cp /tmp/ s3://operator-testing/ --recursive + " + set -o xtrace +} + get_psql_pod_host() { local pod=${1} diff --git a/e2e-tests/tests/custom-extensions/00-deploy-operator.yaml b/e2e-tests/tests/custom-extensions/00-deploy-operator.yaml index 7faf4da852..0cfe9bbd0e 100644 --- a/e2e-tests/tests/custom-extensions/00-deploy-operator.yaml +++ b/e2e-tests/tests/custom-extensions/00-deploy-operator.yaml @@ -12,3 +12,5 @@ commands: deploy_operator deploy_client deploy_s3_secrets + deploy_minio + copy_custom_extensions_form_aws diff --git a/e2e-tests/tests/custom-extensions/02-assert.yaml b/e2e-tests/tests/custom-extensions/02-assert.yaml index 4a86a66c94..ae1514543e 100644 --- a/e2e-tests/tests/custom-extensions/02-assert.yaml +++ b/e2e-tests/tests/custom-extensions/02-assert.yaml @@ -35,15 +35,19 @@ spec: value: s3 - name: STORAGE_ENDPOINT - name: STORAGE_REGION - value: eu-central-1 + value: us-east-1 - name: STORAGE_BUCKET - value: pg-extensions + value: operator-testing - name: INSTALL_EXTENSIONS - name: PG_VERSION - name: PGDATA_EXTENSIONS + - name: STORAGE_DISABLE_SSL + value: "true" + - name: STORAGE_FORCE_PATH_STYLE + value: "true" envFrom: - secretRef: - name: aws-s3-secret + name: minio-secret resources: {} volumeMounts: - mountPath: /pgdata diff --git a/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml b/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml index dbe9380235..7d51929101 100644 --- a/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml +++ b/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml @@ -11,4 +11,4 @@ spec: dynamicConfiguration: postgresql: parameters: - shared_preload_libraries: pg_cron \ No newline at end of file + shared_preload_libraries: pg_cron diff --git a/e2e-tests/tests/custom-extensions/05-assert.yaml b/e2e-tests/tests/custom-extensions/05-assert.yaml index 4a86a66c94..ae1514543e 100644 --- a/e2e-tests/tests/custom-extensions/05-assert.yaml +++ b/e2e-tests/tests/custom-extensions/05-assert.yaml @@ -35,15 +35,19 @@ spec: value: s3 - name: STORAGE_ENDPOINT - name: STORAGE_REGION - value: eu-central-1 + value: us-east-1 - name: STORAGE_BUCKET - value: pg-extensions + value: operator-testing - name: INSTALL_EXTENSIONS - name: PG_VERSION - name: PGDATA_EXTENSIONS + - name: STORAGE_DISABLE_SSL + value: "true" + - name: STORAGE_FORCE_PATH_STYLE + value: "true" envFrom: - secretRef: - name: aws-s3-secret + name: minio-secret resources: {} volumeMounts: - mountPath: /pgdata diff --git a/e2e-tests/tests/custom-extensions/06-assert.yaml b/e2e-tests/tests/custom-extensions/06-assert.yaml index c8b4226623..f0c57e2972 100644 --- a/e2e-tests/tests/custom-extensions/06-assert.yaml +++ b/e2e-tests/tests/custom-extensions/06-assert.yaml @@ -37,15 +37,19 @@ spec: value: s3 - name: STORAGE_ENDPOINT - name: STORAGE_REGION - value: eu-central-1 + value: us-east-1 - name: STORAGE_BUCKET - value: pg-extensions + value: operator-testing - name: INSTALL_EXTENSIONS - name: PG_VERSION - name: PGDATA_EXTENSIONS + - name: STORAGE_DISABLE_SSL + value: "true" + - name: STORAGE_FORCE_PATH_STYLE + value: "true" envFrom: - secretRef: - name: aws-s3-secret + name: minio-secret resources: {} volumeMounts: - mountPath: /pgdata diff --git a/e2e-tests/tests/custom-extensions/10-assert.yaml b/e2e-tests/tests/custom-extensions/10-assert.yaml new file mode 100644 index 0000000000..6c5c6eb780 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/10-assert.yaml @@ -0,0 +1,134 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 180 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: custom-extensions-repo-host + labels: + postgres-operator.crunchydata.com/cluster: custom-extensions + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-extensions + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 4 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: custom-extensions-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: custom-extensions + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-extensions + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-extensions + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-extensions + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 4 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-extensions +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/custom-extensions/10-use-aws-storage.yaml b/e2e-tests/tests/custom-extensions/10-use-aws-storage.yaml new file mode 100644 index 0000000000..f350f7c6c1 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/10-use-aws-storage.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + kubectl patch pg custom-extensions \ + -n "${NAMESPACE}" \ + --type='json' \ + -p='[ + {"op": "remove", "path": "/spec/extensions/storage/disableSSL"}, + {"op": "remove", "path": "/spec/extensions/storage/forcePathStyle"}, + {"op": "replace", "path": "/spec/extensions/storage/secret/name", "value": "aws-s3-secret"}, + {"op": "replace", "path": "/spec/extensions/storage/region", "value": "eu-central-1"}, + {"op": "replace", "path": "/spec/extensions/storage/bucket", "value": "pg-extensions"}, + {"op": "replace", "path": "/spec/extensions/storage/endpoint", "value": "s3.eu-central-1.amazonaws.com"} + ]' diff --git a/e2e-tests/tests/custom-extensions/11-assert.yaml b/e2e-tests/tests/custom-extensions/11-assert.yaml new file mode 100644 index 0000000000..9e347dd025 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/11-assert.yaml @@ -0,0 +1,80 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-extensions + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-extensions + controller: true + blockOwnerDeletion: true +spec: + template: + spec: + initContainers: + - name: postgres-startup + - command: + - /usr/local/bin/relocate-extensions.sh + resources: {} + volumeMounts: + - mountPath: /pgdata + name: postgres-data + - mountPath: /tmp + name: tmp + - command: + - /usr/local/bin/install-extensions.sh + env: + - name: STORAGE_TYPE + value: s3 + - name: STORAGE_ENDPOINT + - name: STORAGE_REGION + value: eu-central-1 + - name: STORAGE_BUCKET + value: pg-extensions + - name: INSTALL_EXTENSIONS + - name: PG_VERSION + - name: PGDATA_EXTENSIONS + envFrom: + - secretRef: + name: aws-s3-secret + resources: {} + volumeMounts: + - mountPath: /pgdata + name: postgres-data + - name: postgres-data + - name: postgres-data + - mountPath: /tmp + name: tmp + - command: + - /usr/local/bin/init-entrypoint.sh + - name: nss-wrapper-init +status: + observedGeneration: 5 + replicas: 1 + updatedReplicas: 1 + readyReplicas: 1 + availableReplicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-extensions +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml b/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml new file mode 100644 index 0000000000..7d51929101 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml @@ -0,0 +1,14 @@ +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-extensions +spec: + extensions: + custom: + - name: pg_cron + version: 1.6.1 + patroni: + dynamicConfiguration: + postgresql: + parameters: + shared_preload_libraries: pg_cron diff --git a/e2e-tests/tests/custom-extensions/12-enable-pg_cron.yaml b/e2e-tests/tests/custom-extensions/12-enable-pg_cron.yaml new file mode 100644 index 0000000000..b0800ef10a --- /dev/null +++ b/e2e-tests/tests/custom-extensions/12-enable-pg_cron.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + wait_cluster_consistency custom-extensions + + run_psql_local '\c postgres \\\ CREATE EXTENSION pg_cron' "postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres)" + timeout: 360 diff --git a/e2e-tests/tests/custom-extensions/13-assert.yaml b/e2e-tests/tests/custom-extensions/13-assert.yaml new file mode 100644 index 0000000000..c56ea2c1fb --- /dev/null +++ b/e2e-tests/tests/custom-extensions/13-assert.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 13-check-extensions +data: + data: |2- + pg_cron + pg_stat_monitor + pgaudit diff --git a/e2e-tests/tests/custom-extensions/13-check-extensions.yaml b/e2e-tests/tests/custom-extensions/13-check-extensions.yaml new file mode 100644 index 0000000000..c187cfd854 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/13-check-extensions.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select name from pg_available_extensions where name in ('pg_cron','pg_stat_monitor','pgaudit') order by name") + + kubectl create configmap -n "${NAMESPACE}" 13-check-extensions --from-literal=data="${data}" diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 47a3dd2cf6..0516b3901c 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -27,6 +27,7 @@ export IMAGE_PMM3_CLIENT=${IMAGE_PMM3_CLIENT:-"perconalab/pmm-client:3-dev-lates export IMAGE_PMM3_SERVER=${IMAGE_PMM3_SERVER:-"perconalab/pmm-server:3-dev-latest"} export PGOV1_TAG=${PGOV1_TAG:-"1.4.0"} export PGOV1_VER=${PGOV1_VER:-"14"} +export MINIO_VER="5.4.0" # shellcheck disable=SC2034 date=$(which gdate || which date) From 1757812d2d93e9a92d04274d9be50a5c208f733b Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 15 Jul 2025 14:06:16 +0300 Subject: [PATCH 093/300] Update e2e-tests/functions Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- e2e-tests/functions | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 3a8dddd4cd..887ef99dae 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -364,9 +364,9 @@ copy_custom_extensions_form_aws() { secret_key="$(kubectl -n "${NAMESPACE}" get secret minio-secret -o jsonpath='{.data.AWS_SECRET_ACCESS_KEY}' | base64 -d)" kubectl -n "${NAMESPACE}" run -i --rm aws-cli \ - --image=perconalab/awscli \ - --restart=Never -- \ - bash -c " + --image=perconalab/awscli \ + --restart=Never -- \ + bash -c " AWS_ACCESS_KEY_ID=$(get_aws_access_key_id aws-s3-secret) \ AWS_SECRET_ACCESS_KEY=$(get_aws_access_key aws-s3-secret) \ AWS_DEFAULT_REGION=eu-central-1 \ From b722493ffb1c807e9e2bfd73d12a18c7dff55ad4 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 15 Jul 2025 13:30:31 +0200 Subject: [PATCH 094/300] K8SPG-777 set crVersion (#1210) * K8SPG-777 set crVersion * delete log * fix import * add test * PR fix * fix imports --------- Co-authored-by: Viacheslav Sarzhan --- .../pgv2.percona.com_perconapgclusters.yaml | 3 + .../pgv2.percona.com_perconapgclusters.yaml | 3 + deploy/bundle.yaml | 3 + deploy/cr.yaml | 2 +- deploy/crd.yaml | 3 + deploy/cw-bundle.yaml | 3 + percona/controller/pgcluster/controller.go | 22 ++++++ .../controller/pgcluster/controller_test.go | 77 ++++++++++++++++++- .../v2/perconapgcluster_types.go | 3 + 9 files changed, 117 insertions(+), 2 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index fd4317efe5..5ed1d26b46 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -5237,6 +5237,9 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. + Version is the application version in the format X.Y.Z (e.g., "2.7.0"). + example: 2.7.0 + pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index a0dccc91bf..e851a61a6f 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -5644,6 +5644,9 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. + Version is the application version in the format X.Y.Z (e.g., "2.7.0"). + example: 2.7.0 + pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 5ec0a7101f..9e13289498 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -5941,6 +5941,9 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. + Version is the application version in the format X.Y.Z (e.g., "2.7.0"). + example: 2.7.0 + pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 5f4cffe8b3..dbb411f051 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,7 +9,7 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: 2.7.0 + crVersion: "2.7.0" # initContainer: # image: perconalab/percona-postgresql-operator:main # resources: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 407ac4d2d9..099dc25262 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -5941,6 +5941,9 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. + Version is the application version in the format X.Y.Z (e.g., "2.7.0"). + example: 2.7.0 + pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 0e0dc91efb..bd0d15c934 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -5941,6 +5941,9 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. + Version is the application version in the format X.Y.Z (e.g., "2.7.0"). + example: 2.7.0 + pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index f3e0d03928..f0623371a0 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -33,6 +33,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" + logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" @@ -49,6 +50,7 @@ import ( "github.com/percona/percona-postgresql-operator/percona/pmm" perconaPG "github.com/percona/percona-postgresql-operator/percona/postgres" "github.com/percona/percona-postgresql-operator/percona/utils/registry" + "github.com/percona/percona-postgresql-operator/percona/version" "github.com/percona/percona-postgresql-operator/percona/watcher" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" @@ -201,6 +203,9 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return ctrl.Result{}, errors.Wrap(err, "get PerconaPGCluster") } + if err := r.setCRVersion(ctx, cr); err != nil { + return reconcile.Result{}, errors.Wrap(err, "set CR version") + } cr.Default() if cr.Spec.OpenShift == nil { @@ -964,3 +969,20 @@ func (r *PGClusterReconciler) ensureFinalizers(ctx context.Context, cr *v2.Perco return nil } + +func (r *PGClusterReconciler) setCRVersion(ctx context.Context, cr *v2.PerconaPGCluster) error { + if len(cr.Spec.CRVersion) > 0 { + return nil + } + + orig := cr.DeepCopy() + cr.Spec.CRVersion = version.Version() + + if err := r.Client.Patch(ctx, cr, client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "patch CR") + } + + logf.FromContext(ctx).Info("Set CR version", "version", cr.Spec.CRVersion) + + return nil +} diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 8ba1ee9ef4..86b8a35ab4 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -27,6 +27,7 @@ import ( "github.com/percona/percona-postgresql-operator/internal/feature" "github.com/percona/percona-postgresql-operator/internal/naming" pNaming "github.com/percona/percona-postgresql-operator/percona/naming" + "github.com/percona/percona-postgresql-operator/percona/version" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -686,7 +687,7 @@ var _ = Describe("Version labels", Ordered, func() { }) cr, err := readDefaultCR(crName, ns) - It("should read defautl cr.yaml", func() { + It("should read default cr.yaml", func() { Expect(err).NotTo(HaveOccurred()) }) @@ -2265,3 +2266,77 @@ var _ = Describe("Init Container", Ordered, func() { }) }) }) + +var _ = Describe("CR Version Management", Ordered, func() { + ctx := context.Background() + const crName = "cr-version" + const ns = crName + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName, + Namespace: ns, + }, + } + + BeforeAll(func() { + By("Creating the Namespace for CR version tests") + err := k8sClient.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the Namespace after CR version tests") + _ = k8sClient.Delete(ctx, namespace) + }) + + Context("setCRVersion logic", Ordered, func() { + When("the CRVersion is already set", func() { + It("should not change the CRVersion", func() { + cr, err := readDefaultCR("cr-version-1", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.CRVersion = "2.7.0" + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + + reconciler := &PGClusterReconciler{Client: k8sClient} + err = reconciler.setCRVersion(ctx, cr) + Expect(err).NotTo(HaveOccurred()) + Expect(cr.Spec.CRVersion).To(Equal("2.7.0")) + }) + }) + + When("the CRVersion is empty", func() { + It("should set CRVersion and patch the resource", func() { + cr, err := readDefaultCR("cr-version-2", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.CRVersion = "" + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + + reconciler := &PGClusterReconciler{Client: k8sClient} + err = reconciler.setCRVersion(ctx, cr) + Expect(err).NotTo(HaveOccurred()) + + // Fetch the CR again to verify the patch was applied in the cluster + updated := &v2.PerconaPGCluster{} + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: cr.Name, Namespace: cr.Namespace}, updated)).Should(Succeed()) + Expect(updated.Spec.CRVersion).To(Equal(version.Version())) + }) + }) + + When("the patch operation fails", func() { + It("should return an error", func() { + cr, err := readDefaultCR("cr-version-3", ns) + Expect(err).NotTo(HaveOccurred()) + cr.Spec.CRVersion = "" + + // Do NOT create the CR in k8s, so Patch will fail (object does not exist) + reconciler := &PGClusterReconciler{Client: k8sClient} + err = reconciler.setCRVersion(ctx, cr) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("patch CR")) + }) + }) + }) +}) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index dd579c5d4d..ff1385ae57 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -52,6 +52,9 @@ type PerconaPGClusterSpec struct { // upgrade to apply changes to Kubernetes objects. Default is the latest // version. // +optional + // Version is the application version in the format X.Y.Z (e.g., "2.7.0"). + // +kubebuilder:validation:Pattern=`^$|^\d+\.\d+\.\d+$` + // +kubebuilder:example="2.7.0" CRVersion string `json:"crVersion,omitempty"` InitContainer *crunchyv1beta1.InitContainerSpec `json:"initContainer,omitempty"` From 2098d676111ee4c012efa542b878dccaf7d8d2e1 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 16 Jul 2025 13:38:58 +0300 Subject: [PATCH 095/300] K8SPG-719 fixes on the deploy_pmm3_server for openshift (#1224) * K8SPG-719 fixes on the deploy_pmm3_server for openshift * shfmt * remove platform specific set * move init on top of the function * add retry func --- e2e-tests/functions | 51 ++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 0a28f8fe0e..0f2cb183d5 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -370,9 +370,14 @@ deploy_pmm_server() { } deploy_pmm3_server() { - helm uninstall -n "${NAMESPACE}" pmm || : + helm uninstall -n "${NAMESPACE}" monitoring || : + helm repo remove percona || : + kubectl delete clusterrole monitoring --ignore-not-found + kubectl delete clusterrolebinding monitoring --ignore-not-found + helm repo add percona https://percona.github.io/percona-helm-charts/ + helm repo update + if [[ $OPENSHIFT ]]; then - platform=openshift oc create sa pmm-server -n "$NAMESPACE" oc adm policy add-scc-to-user privileged -z pmm-server -n "$NAMESPACE" @@ -384,24 +389,32 @@ deploy_pmm3_server() { oc create rolebinding pmm-pg-operator-namespace-only --role percona-postgresql-operator --serviceaccount=$NAMESPACE:pmm-server -n "${NAMESPACE}" oc patch role/percona-postgresql-operator --type json -p='[{"op":"add","path": "/rules/-","value":{"apiGroups":["security.openshift.io"],"resources":["securitycontextconstraints"],"verbs":["use"],"resourceNames":["privileged"]}}]' -n "$NAMESPACE" fi - helm install monitoring --set imageTag=${IMAGE_PMM3_SERVER#*:} --set imageRepo=${IMAGE_PMM3_SERVER%:*} --set platform=$platform --set sa=pmm-server --set supresshttp2=false https://percona-charts.storage.googleapis.com/pmm-server-${PMM_SERVER_VERSION}.tgz -n "$NAMESPACE" - else - platform=kubernetes - - helm uninstall -n "${NAMESPACE}" monitoring || : - helm repo remove percona || : - kubectl delete clusterrole monitoring --ignore-not-found - kubectl delete clusterrolebinding monitoring --ignore-not-found - - helm repo add percona https://percona.github.io/percona-helm-charts/ - helm install monitoring percona/pmm -n "${NAMESPACE}" \ - --set fullnameOverride=monitoring \ - --set image.tag=${IMAGE_PMM3_SERVER#*:} \ - --set image.repository=${IMAGE_PMM3_SERVER%:*} \ - --set service.type=LoadBalancer \ - --set platform="$platform" \ - --force + local additional_params="--set platform=openshift --set supresshttp2=false --set serviceAccount.create=false --set serviceAccount.name=pmm-server" fi + + retry 10 60 helm install monitoring percona/pmm -n "${NAMESPACE}" \ + --set fullnameOverride=monitoring \ + --set image.tag=${IMAGE_PMM3_SERVER#*:} \ + --set image.repository=${IMAGE_PMM3_SERVER%:*} \ + --set service.type=LoadBalancer \ + $additional_params \ + --force +} + +retry() { + local max=$1 + local delay=$2 + shift 2 # cut delay and max args + local n=1 + + until "$@"; do + if [[ $n -ge $max ]]; then + echo "The command '$@' has failed after $n attempts." + exit 1 + fi + ((n++)) + sleep $delay + done } generate_pmm_api_key() { From b565ffc401a3ee63ebed65ce57d4dc3ff6f798ae Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 16 Jul 2025 14:11:17 +0300 Subject: [PATCH 096/300] K8SPG-826 use /tmp/pmm for pmm PMM_AGENT_PATHS_TEMPDIR (#1225) Co-authored-by: Viacheslav Sarzhan --- percona/pmm/pmm.go | 2 +- percona/pmm/pmm_test.go | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index 7308ce98ea..facc3ab512 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -411,7 +411,7 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_PATHS_TEMPDIR", - Value: "/tmp", + Value: "/tmp/pmm", }, }, } diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index 482dfa4f59..daba7cc7fb 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -10,6 +10,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/percona/percona-postgresql-operator/percona/version" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" ) @@ -26,7 +27,7 @@ func TestContainer(t *testing.T) { pgc := &v2.PerconaPGCluster{ Spec: v2.PerconaPGClusterSpec{ - CRVersion: "2.6.0", + CRVersion: version.Version(), PMM: pmmSpec, }, ObjectMeta: metav1.ObjectMeta{ @@ -152,7 +153,7 @@ func TestSidecarContainerV2(t *testing.T) { pgc := &v2.PerconaPGCluster{ Spec: v2.PerconaPGClusterSpec{ - CRVersion: "2.7.0", + CRVersion: version.Version(), PMM: pmmSpec, }, ObjectMeta: metav1.ObjectMeta{ @@ -264,7 +265,7 @@ func TestSidecarContainerV3(t *testing.T) { pgc := &v2.PerconaPGCluster{ Spec: v2.PerconaPGClusterSpec{ - CRVersion: "2.7.0", + CRVersion: version.Version(), PMM: pmmSpec, }, ObjectMeta: metav1.ObjectMeta{ @@ -321,7 +322,7 @@ func TestSidecarContainerV3(t *testing.T) { "DB_USER": v2.UserMonitoring, "DB_PASS": "", // secret reference is asserted separately "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=test-cluster --environment=dev-postgres; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", - "PMM_AGENT_PATHS_TEMPDIR": "/tmp", + "PMM_AGENT_PATHS_TEMPDIR": "/tmp/pmm", } for _, envVar := range container.Env { From 78dc23fbba03b1bad60cdd0ea55323dfc444b7d0 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 16 Jul 2025 13:38:58 +0300 Subject: [PATCH 097/300] K8SPG-719 fixes on the deploy_pmm3_server for openshift (#1224) * K8SPG-719 fixes on the deploy_pmm3_server for openshift * shfmt * remove platform specific set * move init on top of the function * add retry func --- e2e-tests/functions | 51 ++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index a12ef9b6c8..e156c004ea 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -370,9 +370,14 @@ deploy_pmm_server() { } deploy_pmm3_server() { - helm uninstall -n "${NAMESPACE}" pmm || : + helm uninstall -n "${NAMESPACE}" monitoring || : + helm repo remove percona || : + kubectl delete clusterrole monitoring --ignore-not-found + kubectl delete clusterrolebinding monitoring --ignore-not-found + helm repo add percona https://percona.github.io/percona-helm-charts/ + helm repo update + if [[ $OPENSHIFT ]]; then - platform=openshift oc create sa pmm-server -n "$NAMESPACE" oc adm policy add-scc-to-user privileged -z pmm-server -n "$NAMESPACE" @@ -384,24 +389,32 @@ deploy_pmm3_server() { oc create rolebinding pmm-pg-operator-namespace-only --role percona-postgresql-operator --serviceaccount=$NAMESPACE:pmm-server -n "${NAMESPACE}" oc patch role/percona-postgresql-operator --type json -p='[{"op":"add","path": "/rules/-","value":{"apiGroups":["security.openshift.io"],"resources":["securitycontextconstraints"],"verbs":["use"],"resourceNames":["privileged"]}}]' -n "$NAMESPACE" fi - helm install monitoring --set imageTag=${IMAGE_PMM3_SERVER#*:} --set imageRepo=${IMAGE_PMM3_SERVER%:*} --set platform=$platform --set sa=pmm-server --set supresshttp2=false https://percona-charts.storage.googleapis.com/pmm-server-${PMM_SERVER_VERSION}.tgz -n "$NAMESPACE" - else - platform=kubernetes - - helm uninstall -n "${NAMESPACE}" monitoring || : - helm repo remove percona || : - kubectl delete clusterrole monitoring --ignore-not-found - kubectl delete clusterrolebinding monitoring --ignore-not-found - - helm repo add percona https://percona.github.io/percona-helm-charts/ - helm install monitoring percona/pmm -n "${NAMESPACE}" \ - --set fullnameOverride=monitoring \ - --set image.tag=${IMAGE_PMM3_SERVER#*:} \ - --set image.repository=${IMAGE_PMM3_SERVER%:*} \ - --set service.type=LoadBalancer \ - --set platform="$platform" \ - --force + local additional_params="--set platform=openshift --set supresshttp2=false --set serviceAccount.create=false --set serviceAccount.name=pmm-server" fi + + retry 10 60 helm install monitoring percona/pmm -n "${NAMESPACE}" \ + --set fullnameOverride=monitoring \ + --set image.tag=${IMAGE_PMM3_SERVER#*:} \ + --set image.repository=${IMAGE_PMM3_SERVER%:*} \ + --set service.type=LoadBalancer \ + $additional_params \ + --force +} + +retry() { + local max=$1 + local delay=$2 + shift 2 # cut delay and max args + local n=1 + + until "$@"; do + if [[ $n -ge $max ]]; then + echo "The command '$@' has failed after $n attempts." + exit 1 + fi + ((n++)) + sleep $delay + done } generate_pmm_api_key() { From 49da79ed430ea16c2375dd60d10ef31f638434d9 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 16 Jul 2025 14:11:17 +0300 Subject: [PATCH 098/300] K8SPG-826 use /tmp/pmm for pmm PMM_AGENT_PATHS_TEMPDIR (#1225) Co-authored-by: Viacheslav Sarzhan --- percona/pmm/pmm.go | 2 +- percona/pmm/pmm_test.go | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index 7308ce98ea..facc3ab512 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -411,7 +411,7 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_PATHS_TEMPDIR", - Value: "/tmp", + Value: "/tmp/pmm", }, }, } diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index 482dfa4f59..daba7cc7fb 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -10,6 +10,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/percona/percona-postgresql-operator/percona/version" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" ) @@ -26,7 +27,7 @@ func TestContainer(t *testing.T) { pgc := &v2.PerconaPGCluster{ Spec: v2.PerconaPGClusterSpec{ - CRVersion: "2.6.0", + CRVersion: version.Version(), PMM: pmmSpec, }, ObjectMeta: metav1.ObjectMeta{ @@ -152,7 +153,7 @@ func TestSidecarContainerV2(t *testing.T) { pgc := &v2.PerconaPGCluster{ Spec: v2.PerconaPGClusterSpec{ - CRVersion: "2.7.0", + CRVersion: version.Version(), PMM: pmmSpec, }, ObjectMeta: metav1.ObjectMeta{ @@ -264,7 +265,7 @@ func TestSidecarContainerV3(t *testing.T) { pgc := &v2.PerconaPGCluster{ Spec: v2.PerconaPGClusterSpec{ - CRVersion: "2.7.0", + CRVersion: version.Version(), PMM: pmmSpec, }, ObjectMeta: metav1.ObjectMeta{ @@ -321,7 +322,7 @@ func TestSidecarContainerV3(t *testing.T) { "DB_USER": v2.UserMonitoring, "DB_PASS": "", // secret reference is asserted separately "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=test-cluster --environment=dev-postgres; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", - "PMM_AGENT_PATHS_TEMPDIR": "/tmp", + "PMM_AGENT_PATHS_TEMPDIR": "/tmp/pmm", } for _, envVar := range container.Env { From 04c9d075a8290b2b40ba6f9fa0e0e5764d014ac8 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 16 Jul 2025 20:07:16 +0200 Subject: [PATCH 099/300] K8SPG-777 delete verification (#1227) --- .../percona/generated/pgv2.percona.com_perconapgclusters.yaml | 3 --- config/crd/bases/pgv2.percona.com_perconapgclusters.yaml | 3 --- deploy/bundle.yaml | 3 --- deploy/cr.yaml | 2 +- deploy/crd.yaml | 3 --- deploy/cw-bundle.yaml | 3 --- pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go | 3 --- 7 files changed, 1 insertion(+), 19 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 5ed1d26b46..fd4317efe5 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -5237,9 +5237,6 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. - Version is the application version in the format X.Y.Z (e.g., "2.7.0"). - example: 2.7.0 - pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index e851a61a6f..a0dccc91bf 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -5644,9 +5644,6 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. - Version is the application version in the format X.Y.Z (e.g., "2.7.0"). - example: 2.7.0 - pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 9e13289498..5ec0a7101f 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -5941,9 +5941,6 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. - Version is the application version in the format X.Y.Z (e.g., "2.7.0"). - example: 2.7.0 - pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/deploy/cr.yaml b/deploy/cr.yaml index dbb411f051..5f4cffe8b3 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,7 +9,7 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: "2.7.0" + crVersion: 2.7.0 # initContainer: # image: perconalab/percona-postgresql-operator:main # resources: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 099dc25262..407ac4d2d9 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -5941,9 +5941,6 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. - Version is the application version in the format X.Y.Z (e.g., "2.7.0"). - example: 2.7.0 - pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index bd0d15c934..0e0dc91efb 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -5941,9 +5941,6 @@ spec: Version of the operator. Update this to new version after operator upgrade to apply changes to Kubernetes objects. Default is the latest version. - Version is the application version in the format X.Y.Z (e.g., "2.7.0"). - example: 2.7.0 - pattern: ^$|^\d+\.\d+\.\d+$ type: string dataSource: description: Specifies a data source for bootstrapping the PostgreSQL diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index ff1385ae57..dd579c5d4d 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -52,9 +52,6 @@ type PerconaPGClusterSpec struct { // upgrade to apply changes to Kubernetes objects. Default is the latest // version. // +optional - // Version is the application version in the format X.Y.Z (e.g., "2.7.0"). - // +kubebuilder:validation:Pattern=`^$|^\d+\.\d+\.\d+$` - // +kubebuilder:example="2.7.0" CRVersion string `json:"crVersion,omitempty"` InitContainer *crunchyv1beta1.InitContainerSpec `json:"initContainer,omitempty"` From e92bc123958f94d6db5ab4843ef1b0971a5fe0ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 21:07:36 +0300 Subject: [PATCH 100/300] CLOUD-727: Bump golang.org/x/tools from 0.34.0 to 0.35.0 (#1223) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.34.0 to 0.35.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.34.0...v0.35.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.35.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 066129fe58..a95b5c268e 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.39.0 + golang.org/x/crypto v0.40.0 google.golang.org/grpc v1.73.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.33.2 @@ -56,7 +56,7 @@ require ( go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/mod v0.25.0 // indirect + golang.org/x/mod v0.26.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect ) @@ -115,14 +115,14 @@ require ( go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.41.0 // indirect + golang.org/x/net v0.42.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.15.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.26.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.34.0 // indirect + golang.org/x/term v0.33.0 // indirect + golang.org/x/text v0.27.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.34.0 + golang.org/x/tools v0.35.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect diff --git a/go.sum b/go.sum index aca8f36098..509d8047d6 100644 --- a/go.sum +++ b/go.sum @@ -249,29 +249,29 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -280,18 +280,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= +golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -299,8 +299,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From c02af8213b619cec3194a3c56485de8bc9b9ddea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valmira=20Nogueira=20Corr=C3=AAa?= Date: Thu, 17 Jul 2025 04:44:26 -0300 Subject: [PATCH 101/300] K8SPG-646 - Extend test to verify CA update (#1221) * Extend test to verify CA update * Add missing function and fix end of the file lines * Wait for Cert Manager to be ready * Fix DNS names * Add verification for cert manager webhook to be ready * Undeploy cert manager during the test * Add PG pause before changing the certificates --- e2e-tests/functions | 27 +++++- e2e-tests/tests/custom-tls/06-assert.yaml | 45 ++++++++++ .../tests/custom-tls/06-create-new-ca.yaml | 26 ++++++ e2e-tests/tests/custom-tls/07-assert.yaml | 90 +++++++++++++++++++ .../tests/custom-tls/07-create-new-certs.yaml | 51 +++++++++++ e2e-tests/tests/custom-tls/08-assert.yaml | 75 ++++++++++++++++ .../tests/custom-tls/08-pause-cluster.yaml | 13 +++ e2e-tests/tests/custom-tls/09-assert.yaml | 90 +++++++++++++++++++ .../tests/custom-tls/09-upgrade-cluster.yaml | 20 +++++ .../tests/custom-tls/10-verify-new-certs.yaml | 16 ++++ e2e-tests/tests/custom-tls/11-write-data.yaml | 17 ++++ .../12-verify-data-written-in-primary.yaml | 16 ++++ .../99-remove-cluster-gracefully.yaml | 1 + 13 files changed, 485 insertions(+), 2 deletions(-) create mode 100644 e2e-tests/tests/custom-tls/06-assert.yaml create mode 100644 e2e-tests/tests/custom-tls/06-create-new-ca.yaml create mode 100644 e2e-tests/tests/custom-tls/07-assert.yaml create mode 100644 e2e-tests/tests/custom-tls/07-create-new-certs.yaml create mode 100644 e2e-tests/tests/custom-tls/08-assert.yaml create mode 100644 e2e-tests/tests/custom-tls/08-pause-cluster.yaml create mode 100644 e2e-tests/tests/custom-tls/09-assert.yaml create mode 100644 e2e-tests/tests/custom-tls/09-upgrade-cluster.yaml create mode 100644 e2e-tests/tests/custom-tls/10-verify-new-certs.yaml create mode 100644 e2e-tests/tests/custom-tls/11-write-data.yaml create mode 100644 e2e-tests/tests/custom-tls/12-verify-data-written-in-primary.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index 0f2cb183d5..817c9233ca 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -240,6 +240,13 @@ get_cr() { cat $TEMP_DIR/cr.yaml } +run_comand_on_pod() { + local command=${1} + + kubectl -n ${NAMESPACE} exec $(get_client_pod) -- \ + bash -c "$command" +} + run_psql_local() { local command=${1} local uri=${2} @@ -909,11 +916,27 @@ wait_cluster_consistency() { } deploy_cert_manager() { + destroy_cert_manager + echo 'deploy cert manager' kubectl create namespace cert-manager || : kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true || : - kubectl apply -f "https://github.com/jetstack/cert-manager/releases/download/v${CERT_MANAGER_VER}/cert-manager.yaml" --validate=false || : 2>/dev/null - sleep 70 + kubectl apply -f "https://github.com/jetstack/cert-manager/releases/download/v${CERT_MANAGER_VER}/cert-manager.yaml" --validate=false > /dev/null 2>&1 || : + + kubectl wait deployment cert-manager cert-manager-webhook cert-manager-cainjector \ + --for=condition=available \ + --timeout=100s \ + --namespace cert-manager + + echo "Waiting for cert-manager webhook to be ready..." + until kubectl get validatingwebhookconfiguration cert-manager-webhook -o jsonpath='{.webhooks[0].clientConfig.caBundle}' | grep -q '[A-Za-z0-9+/=]'; do + sleep 5 + done +} + +destroy_cert_manager() { + kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v${CERT_MANAGER_VER}/cert-manager.yaml > /dev/null 2>&1 || : + kubectl delete --grace-period=0 --force=true namespace cert-manager > /dev/null 2>&1 || : } get_container_image() { diff --git a/e2e-tests/tests/custom-tls/06-assert.yaml b/e2e-tests/tests/custom-tls/06-assert.yaml new file mode 100644 index 0000000000..5a3fcf99a6 --- /dev/null +++ b/e2e-tests/tests/custom-tls/06-assert.yaml @@ -0,0 +1,45 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 100 +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: new-custom-cert-tls-pg-ca-issuer +spec: + selfSigned: {} +status: + conditions: + - observedGeneration: 1 + reason: IsReady + status: "True" + type: Ready +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + generation: 1 + name: new-custom-cert-tls-pg-ca-cert +spec: + commonName: new-postgres-operator-ca + duration: 26280h0m0s + isCA: true + issuerRef: + kind: Issuer + name: new-custom-cert-tls-pg-ca-issuer + renewBefore: 730h0m0s + secretName: new-custom-cert-tls-pg-ca-cert + privateKey: + algorithm: ECDSA + size: 384 + usages: + - cert sign + - crl sign +status: + conditions: + - message: Certificate is up to date and has not expired + observedGeneration: 1 + reason: Ready + status: "True" + type: Ready + revision: 1 diff --git a/e2e-tests/tests/custom-tls/06-create-new-ca.yaml b/e2e-tests/tests/custom-tls/06-create-new-ca.yaml new file mode 100644 index 0000000000..2752520f83 --- /dev/null +++ b/e2e-tests/tests/custom-tls/06-create-new-ca.yaml @@ -0,0 +1,26 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: new-custom-cert-tls-pg-ca-issuer +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: new-custom-cert-tls-pg-ca-cert +spec: + isCA: true + commonName: new-postgres-operator-ca + secretName: new-custom-cert-tls-pg-ca-cert + privateKey: + algorithm: ECDSA + size: 384 + issuerRef: + name: new-custom-cert-tls-pg-ca-issuer + kind: Issuer + duration: 26280h0m0s + renewBefore: 730h0m0s + usages: + - "cert sign" + - "crl sign" diff --git a/e2e-tests/tests/custom-tls/07-assert.yaml b/e2e-tests/tests/custom-tls/07-assert.yaml new file mode 100644 index 0000000000..42a8eba723 --- /dev/null +++ b/e2e-tests/tests/custom-tls/07-assert.yaml @@ -0,0 +1,90 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 100 +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + generation: 1 + name: new-custom-cert-tls-pg-issuer +spec: + ca: + secretName: new-custom-cert-tls-pg-ca-cert +status: + conditions: + - message: Signing CA verified + observedGeneration: 1 + reason: KeyPairVerified + status: "True" + type: Ready +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + generation: 1 + name: new-custom-cert-tls-ssl +spec: + commonName: custom-tls-primary + issuerRef: + kind: Issuer + name: new-custom-cert-tls-pg-issuer + secretName: new-custom-cert-tls-ssl +status: + conditions: + - message: Certificate is up to date and has not expired + observedGeneration: 1 + reason: Ready + status: "True" + type: Ready +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + generation: 1 + name: new-custom-cert-tls-ssl-replica +spec: + commonName: _crunchyrepl + issuerRef: + kind: Issuer + name: new-custom-cert-tls-pg-issuer + secretName: new-custom-cert-tls-ssl-replica +status: + conditions: + - message: Certificate is up to date and has not expired + observedGeneration: 1 + reason: Ready + status: "True" + type: Ready +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + cert-manager.io/alt-names: "" + cert-manager.io/certificate-name: new-custom-cert-tls-pg-ca-cert + cert-manager.io/common-name: new-postgres-operator-ca + cert-manager.io/ip-sans: "" + cert-manager.io/issuer-group: "" + cert-manager.io/issuer-kind: Issuer + cert-manager.io/issuer-name: new-custom-cert-tls-pg-ca-issuer + cert-manager.io/uri-sans: "" + labels: + controller.cert-manager.io/fao: "true" + name: new-custom-cert-tls-pg-ca-cert +type: kubernetes.io/tls +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + controller.cert-manager.io/fao: "true" + name: new-custom-cert-tls-ssl +type: kubernetes.io/tls +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + controller.cert-manager.io/fao: "true" + name: new-custom-cert-tls-ssl-replica +type: kubernetes.io/tls diff --git a/e2e-tests/tests/custom-tls/07-create-new-certs.yaml b/e2e-tests/tests/custom-tls/07-create-new-certs.yaml new file mode 100644 index 0000000000..bb01ef2945 --- /dev/null +++ b/e2e-tests/tests/custom-tls/07-create-new-certs.yaml @@ -0,0 +1,51 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: new-custom-cert-tls-pg-issuer +spec: + ca: + secretName: new-custom-cert-tls-pg-ca-cert +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + generation: 1 + name: new-custom-cert-tls-ssl +spec: + commonName: custom-tls-primary + dnsNames: + - custom-tls-primary.$NAMESPACE.svc.cluster.local + - custom-tls-primary.$NAMESPACE.svc + - custom-tls-primary.$NAMESPACE + - custom-tls-primary + - custom-tls-replicas.$NAMESPACE.svc.cluster.local + - custom-tls-replicas.$NAMESPACE.svc + - custom-tls-replicas.$NAMESPACE + - custom-tls-replicas + issuerRef: + kind: Issuer + name: new-custom-cert-tls-pg-issuer + secretName: new-custom-cert-tls-ssl + privateKey: + algorithm: ECDSA + size: 384 + usages: + - "digital signature" + - "key encipherment" +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: new-custom-cert-tls-ssl-replica +spec: + commonName: _crunchyrepl + issuerRef: + kind: Issuer + name: new-custom-cert-tls-pg-issuer + secretName: new-custom-cert-tls-ssl-replica + privateKey: + algorithm: ECDSA + size: 384 + usages: + - "digital signature" + - "key encipherment" diff --git a/e2e-tests/tests/custom-tls/08-assert.yaml b/e2e-tests/tests/custom-tls/08-assert.yaml new file mode 100644 index 0000000000..7e8f07257b --- /dev/null +++ b/e2e-tests/tests/custom-tls/08-assert.yaml @@ -0,0 +1,75 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-tls + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-tls + controller: true + blockOwnerDeletion: true +status: + replicas: 0 + availableReplicas: 0 + collisionCount: 0 + observedGeneration: 2 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: custom-tls-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: custom-tls + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '2' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-tls + controller: true + blockOwnerDeletion: true +spec: + replicas: 0 +status: + observedGeneration: 2 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-tls + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-tls + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + observedGeneration: 2 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-tls +status: + observedGeneration: 2 + pgbouncer: + ready: 0 + size: 0 + postgres: + instances: + - name: instance1 + ready: 0 + size: 0 + ready: 0 + size: 0 + state: paused diff --git a/e2e-tests/tests/custom-tls/08-pause-cluster.yaml b/e2e-tests/tests/custom-tls/08-pause-cluster.yaml new file mode 100644 index 0000000000..b8a6dfcb03 --- /dev/null +++ b/e2e-tests/tests/custom-tls/08-pause-cluster.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 250 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "custom-tls" ${RANDOM} \ + | yq '.spec.pause=true' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/custom-tls/09-assert.yaml b/e2e-tests/tests/custom-tls/09-assert.yaml new file mode 100644 index 0000000000..2a7385a451 --- /dev/null +++ b/e2e-tests/tests/custom-tls/09-assert.yaml @@ -0,0 +1,90 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 100 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-tls + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-tls + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 4 + replicas: 1 + readyReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: custom-tls-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: custom-tls + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '3' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-tls + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 3 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-tls + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-tls + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 3 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-tls +status: + observedGeneration: 3 + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/custom-tls/09-upgrade-cluster.yaml b/e2e-tests/tests/custom-tls/09-upgrade-cluster.yaml new file mode 100644 index 0000000000..a0147440fd --- /dev/null +++ b/e2e-tests/tests/custom-tls/09-upgrade-cluster.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "custom-tls" ${RANDOM} \ + | yq '.spec.pause=false' \ + | yq '.spec.secrets.customRootCATLSSecret.name="new-custom-cert-tls-pg-ca-cert"' \ + | yq '.spec.secrets.customRootCATLSSecret.items[0].key="tls.key"' \ + | yq '.spec.secrets.customRootCATLSSecret.items[0].path="root.key"' \ + | yq '.spec.secrets.customRootCATLSSecret.items[1].key="tls.crt"' \ + | yq '.spec.secrets.customRootCATLSSecret.items[1].path="root.crt"' \ + | yq '.spec.secrets.customTLSSecret.name="new-custom-cert-tls-ssl"' \ + | yq '.spec.secrets.customReplicationTLSSecret.name="new-custom-cert-tls-ssl-replica"' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/custom-tls/10-verify-new-certs.yaml b/e2e-tests/tests/custom-tls/10-verify-new-certs.yaml new file mode 100644 index 0000000000..fca1041081 --- /dev/null +++ b/e2e-tests/tests/custom-tls/10-verify-new-certs.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + pg_certificate_data=$(run_comand_on_pod "openssl s_client -connect custom-tls-primary:5432 -starttls postgres <<< '' | openssl x509 -noout -subject -issuer -dates -serial") + + if [[ "$pg_certificate_data" != *"subject=CN=custom-tls-primary"* || "$pg_certificate_data" != *"issuer=CN=new-postgres-operator-ca"* ]]; then + echo "Postgres not configured with the new certificate" + exit 1 + fi diff --git a/e2e-tests/tests/custom-tls/11-write-data.yaml b/e2e-tests/tests/custom-tls/11-write-data.yaml new file mode 100644 index 0000000000..c933aa7a68 --- /dev/null +++ b/e2e-tests/tests/custom-tls/11-write-data.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'CREATE DATABASE newapp; \c newapp \\\ CREATE TABLE IF NOT EXISTS newApp (id int PRIMARY KEY);' \ + "postgres:$(get_psql_user_pass custom-tls-pguser-postgres)@$(get_psql_user_host custom-tls-pguser-postgres)" + + run_psql_local \ + '\c newapp \\\ INSERT INTO newApp (id) VALUES (100600)' \ + "postgres:$(get_psql_user_pass custom-tls-pguser-postgres)@$(get_psql_user_host custom-tls-pguser-postgres)" diff --git a/e2e-tests/tests/custom-tls/12-verify-data-written-in-primary.yaml b/e2e-tests/tests/custom-tls/12-verify-data-written-in-primary.yaml new file mode 100644 index 0000000000..46bede1ea4 --- /dev/null +++ b/e2e-tests/tests/custom-tls/12-verify-data-written-in-primary.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(run_psql_local '\c newapp \\\ SELECT * from newApp;' "postgres:$(get_psql_user_pass custom-tls-pguser-postgres)@$(get_psql_user_host custom-tls-pguser-postgres)") + + if [[ "$data" != *"100600"* ]]; then + echo "Missing data in primary" + exit 1 + fi diff --git a/e2e-tests/tests/custom-tls/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/custom-tls/99-remove-cluster-gracefully.yaml index dfffdbf4dd..66f084adf4 100644 --- a/e2e-tests/tests/custom-tls/99-remove-cluster-gracefully.yaml +++ b/e2e-tests/tests/custom-tls/99-remove-cluster-gracefully.yaml @@ -18,4 +18,5 @@ commands: remove_all_finalizers destroy_operator + destroy_cert_manager timeout: 60 From 54b12cc744df8c1142bb9a4788621b9bd0fb34f3 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 17 Jul 2025 11:06:40 +0300 Subject: [PATCH 102/300] K8SPG-757: restricted security context for patroni version check container (#1202) https://perconadev.atlassian.net/browse/K8SPG-757 Co-authored-by: Viacheslav Sarzhan --- percona/controller/pgcluster/controller.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index f0623371a0..cc397bef59 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -39,6 +39,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" "github.com/percona/percona-postgresql-operator/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/internal/logging" "github.com/percona/percona-postgresql-operator/internal/naming" "github.com/percona/percona-postgresql-operator/internal/postgres" @@ -436,7 +437,8 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, Args: []string{ "-c", "sleep 60", }, - Resources: cr.Spec.InstanceSets[0].Resources, + Resources: cr.Spec.InstanceSets[0].Resources, + SecurityContext: initialize.RestrictedSecurityContext(cr.CompareVersion("2.5.0") >= 0), }, }, SecurityContext: cr.Spec.InstanceSets[0].SecurityContext, From 6ef3702c06627b0ad83819e4fa46dc12e6881fdb Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 17 Jul 2025 16:17:00 +0300 Subject: [PATCH 103/300] add minio secret file --- e2e-tests/conf/minio-secret.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 e2e-tests/conf/minio-secret.yml diff --git a/e2e-tests/conf/minio-secret.yml b/e2e-tests/conf/minio-secret.yml new file mode 100644 index 0000000000..1c44db1c1f --- /dev/null +++ b/e2e-tests/conf/minio-secret.yml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: minio-secret +type: Opaque +data: + AWS_ACCESS_KEY_ID: c29tZS1hY2Nlc3Mta2V5 + AWS_SECRET_ACCESS_KEY: c29tZS1zZWNyZXQta2V5 From 19b203cb0d39b1e1762d933f9b19b782344a443e Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 17 Jul 2025 19:37:20 +0300 Subject: [PATCH 104/300] K8SPG-570 update custom secret with labels when they are missing, update missing secret data with autogeneration (#1218) * K8SPG-570 update custom secret with labels when they are missing * use patch instead of update * adjustsments on the logic * fix concurrency issue by checking the secret update * update e2e test * add reset/set scenario on e2e test * cr: bring back if err == nil for apply secrets, the secret is always overwritten * cr: use OnError instead of RetryOnConflict * cr: fix needsUpdate return early --------- Co-authored-by: Viacheslav Sarzhan --- .../users/14-write-data-to-custom-db.yaml | 1 - e2e-tests/tests/users/16-assert.yaml | 49 ++++++++ ...-user-with-predefined-password-secret.yaml | 15 +++ ...data-user-db-with-predefined-password.yaml | 22 ++++ e2e-tests/tests/users/18-assert.yaml | 10 ++ ...from-user-db-with-predefined-password.yaml | 19 +++ .../19-reset-predefined-user-password.yaml | 13 ++ ...ser-db-with-reset-predefined-password.yaml | 22 ++++ ...-user-with-predefined-password-secret.yaml | 12 ++ ...ser-db-again-with-predefined-password.yaml | 22 ++++ .../controller/postgrescluster/postgres.go | 117 ++++++++++++++++++ 11 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 e2e-tests/tests/users/16-assert.yaml create mode 100644 e2e-tests/tests/users/16-create-user-with-predefined-password-secret.yaml create mode 100644 e2e-tests/tests/users/17-write-data-user-db-with-predefined-password.yaml create mode 100644 e2e-tests/tests/users/18-assert.yaml create mode 100644 e2e-tests/tests/users/18-read-from-user-db-with-predefined-password.yaml create mode 100644 e2e-tests/tests/users/19-reset-predefined-user-password.yaml create mode 100644 e2e-tests/tests/users/20-write-data-user-db-with-reset-predefined-password.yaml create mode 100644 e2e-tests/tests/users/21-set-again-user-with-predefined-password-secret.yaml create mode 100644 e2e-tests/tests/users/22-write-data-user-db-again-with-predefined-password.yaml diff --git a/e2e-tests/tests/users/14-write-data-to-custom-db.yaml b/e2e-tests/tests/users/14-write-data-to-custom-db.yaml index 7c37c66517..e395acbb7b 100644 --- a/e2e-tests/tests/users/14-write-data-to-custom-db.yaml +++ b/e2e-tests/tests/users/14-write-data-to-custom-db.yaml @@ -13,7 +13,6 @@ commands: schema='public' hostname=$(get_pgbouncer_host chico-credentials) - run_psql \ 'SET search_path TO public;CREATE TABLE IF NOT EXISTS customApp (id int PRIMARY KEY);' \ "-h $hostname -U $user -d $db_name" "$password" diff --git a/e2e-tests/tests/users/16-assert.yaml b/e2e-tests/tests/users/16-assert.yaml new file mode 100644 index 0000000000..934432d24b --- /dev/null +++ b/e2e-tests/tests/users/16-assert.yaml @@ -0,0 +1,49 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: users + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: users + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: users +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/users/16-create-user-with-predefined-password-secret.yaml b/e2e-tests/tests/users/16-create-user-with-predefined-password-secret.yaml new file mode 100644 index 0000000000..e487590b40 --- /dev/null +++ b/e2e-tests/tests/users/16-create-user-with-predefined-password-secret.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n ${NAMESPACE} create secret generic eagle-credentials --from-literal=password=eagle-db-password + sleep 5 + + kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=json -p '[{"op":"add", "path":"/spec/autoCreateUserSchema","value":true},{"op":"add", "path":"/spec/users","value":[{"name":"eagle","databases":["nest"],"password":{"type":"ASCII"},"secretName":"eagle-credentials"}]}]' + sleep 15 diff --git a/e2e-tests/tests/users/17-write-data-user-db-with-predefined-password.yaml b/e2e-tests/tests/users/17-write-data-user-db-with-predefined-password.yaml new file mode 100644 index 0000000000..ff1239a004 --- /dev/null +++ b/e2e-tests/tests/users/17-write-data-user-db-with-predefined-password.yaml @@ -0,0 +1,22 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + predefinedPassword=eagle-db-password + user='eagle' + db_name='nest' + schema='eagle' + hostname=$(get_pgbouncer_host eagle-credentials) + + run_psql \ + 'CREATE TABLE IF NOT EXISTS customApp (id int PRIMARY KEY);' \ + "-h $hostname -U $user -d $db_name" "$predefinedPassword" + run_psql \ + "INSERT INTO $schema.customApp (id) VALUES (100500)" \ + "-h $hostname -U $user -d $db_name" "$predefinedPassword" + diff --git a/e2e-tests/tests/users/18-assert.yaml b/e2e-tests/tests/users/18-assert.yaml new file mode 100644 index 0000000000..6824d5be2e --- /dev/null +++ b/e2e-tests/tests/users/18-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 18-read-from-user-db-with-predefined-password +data: + data: ' 100500' \ No newline at end of file diff --git a/e2e-tests/tests/users/18-read-from-user-db-with-predefined-password.yaml b/e2e-tests/tests/users/18-read-from-user-db-with-predefined-password.yaml new file mode 100644 index 0000000000..a8151a972c --- /dev/null +++ b/e2e-tests/tests/users/18-read-from-user-db-with-predefined-password.yaml @@ -0,0 +1,19 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + predefinedPassword=eagle-db-password + user='eagle' + db_name='nest' + schema='eagle' + hostname=$(get_pgbouncer_host eagle-credentials) + + data=$(run_psql "SELECT * from $schema.customApp;" "-h $hostname -U $user -d $db_name" "$predefinedPassword") + + kubectl create configmap -n "${NAMESPACE}" 18-read-from-user-db-with-predefined-password --from-literal=data="${data}" diff --git a/e2e-tests/tests/users/19-reset-predefined-user-password.yaml b/e2e-tests/tests/users/19-reset-predefined-user-password.yaml new file mode 100644 index 0000000000..4e58782368 --- /dev/null +++ b/e2e-tests/tests/users/19-reset-predefined-user-password.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n ${NAMESPACE} patch secret eagle-credentials --type merge --patch '{"stringData": {"password": "", "verifier":""}}' + + sleep 5 \ No newline at end of file diff --git a/e2e-tests/tests/users/20-write-data-user-db-with-reset-predefined-password.yaml b/e2e-tests/tests/users/20-write-data-user-db-with-reset-predefined-password.yaml new file mode 100644 index 0000000000..4d12153848 --- /dev/null +++ b/e2e-tests/tests/users/20-write-data-user-db-with-reset-predefined-password.yaml @@ -0,0 +1,22 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + resetPassword=$(get_psql_user_pass eagle-credentials) + user='eagle' + db_name='nest' + schema='eagle' + hostname=$(get_pgbouncer_host eagle-credentials) + + run_psql \ + 'CREATE TABLE IF NOT EXISTS customApp (id int PRIMARY KEY);' \ + "-h $hostname -U $user -d $db_name" "$resetPassword" + run_psql \ + "INSERT INTO $schema.customApp (id) VALUES (100501)" \ + "-h $hostname -U $user -d $db_name" "$resetPassword" + diff --git a/e2e-tests/tests/users/21-set-again-user-with-predefined-password-secret.yaml b/e2e-tests/tests/users/21-set-again-user-with-predefined-password-secret.yaml new file mode 100644 index 0000000000..e12797c2fa --- /dev/null +++ b/e2e-tests/tests/users/21-set-again-user-with-predefined-password-secret.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n ${NAMESPACE} patch secret eagle-credentials --type merge --patch '{"stringData": {"password": "eagle-db-password", "verifier":""}}' + sleep 5 diff --git a/e2e-tests/tests/users/22-write-data-user-db-again-with-predefined-password.yaml b/e2e-tests/tests/users/22-write-data-user-db-again-with-predefined-password.yaml new file mode 100644 index 0000000000..e96fea75f0 --- /dev/null +++ b/e2e-tests/tests/users/22-write-data-user-db-again-with-predefined-password.yaml @@ -0,0 +1,22 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + resetPassword=eagle-db-password + user='eagle' + db_name='nest' + schema='eagle' + hostname=$(get_pgbouncer_host eagle-credentials) + + run_psql \ + 'CREATE TABLE IF NOT EXISTS customApp (id int PRIMARY KEY);' \ + "-h $hostname -U $user -d $db_name" "$resetPassword" + run_psql \ + "INSERT INTO $schema.customApp (id) VALUES (100502)" \ + "-h $hostname -U $user -d $db_name" "$resetPassword" + diff --git a/internal/controller/postgrescluster/postgres.go b/internal/controller/postgrescluster/postgres.go index 22e9e5453e..3064cedc5b 100644 --- a/internal/controller/postgrescluster/postgres.go +++ b/internal/controller/postgrescluster/postgres.go @@ -19,10 +19,13 @@ import ( "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/percona/percona-postgresql-operator/internal/feature" @@ -494,6 +497,17 @@ func (r *Reconciler) reconcilePostgresUserSecrets( userSpecs[string(specUsers[i].Name)] = &specUsers[i] } + // K8SPG-570 for secrets that were created manually, update them + // with the right labels so that the selector called next to track them + // and utilize their data. + for _, user := range specUsers { + if user.SecretName != "" { + if err := r.updateCustomSecretLabels(ctx, cluster, user); err != nil { + return specUsers, nil, err + } + } + } + secrets := &corev1.SecretList{} selector, err := naming.AsSelector(naming.ClusterPostgresUsers(cluster.Name)) if err == nil { @@ -582,6 +596,109 @@ func (r *Reconciler) reconcilePostgresUserSecrets( return specUsers, userSecrets, err } +// K8SPG-570 +// updateCustomSecretLabels checks if a custom secret exists - can be created manually through +// kubectl apply - and updates it with required labels if they are missing. This enables the +// naming.AsSelector(naming.ClusterPostgresUsers(cluster.Name)) to identify these secrets. +func (r *Reconciler) updateCustomSecretLabels( + ctx context.Context, cluster *v1beta1.PostgresCluster, user v1beta1.PostgresUserSpec, +) error { + secretName := string(user.SecretName) + userName := string(user.Name) + + secret := &corev1.Secret{} + err := r.Client.Get(ctx, types.NamespacedName{ + Name: secretName, + Namespace: cluster.Namespace, + }, secret) + if err != nil { + if k8serrors.IsNotFound(err) { + return nil + } + return errors.Wrap(err, fmt.Sprintf("failed to get user %s secret %s", userName, secretName)) + } + + requiredLabels := map[string]string{ + naming.LabelCluster: cluster.Name, + naming.LabelPostgresUser: userName, + naming.LabelRole: naming.RolePostgresUser, + } + + needsUpdate := false + if secret.Labels == nil { + secret.Labels = make(map[string]string) + } + + for labelKey, labelValue := range requiredLabels { + if existing, exists := secret.Labels[labelKey]; !exists || existing != labelValue { + secret.Labels[labelKey] = labelValue + needsUpdate = true + } + } + + if !needsUpdate { + return nil + } + + updateErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + current := &corev1.Secret{} + if err := r.Client.Get(ctx, types.NamespacedName{ + Name: secretName, + Namespace: cluster.Namespace, + }, current); err != nil { + return err + } + + currentOrig := current.DeepCopy() + if current.Labels == nil { + current.Labels = make(map[string]string) + } + + updateNeeded := false + for labelKey, labelValue := range requiredLabels { + if existing, exists := current.Labels[labelKey]; !exists || existing != labelValue { + current.Labels[labelKey] = labelValue + updateNeeded = true + } + } + + if !updateNeeded { + return nil + } + + return r.Client.Patch(ctx, current, client.MergeFrom(currentOrig)) + }) + + if updateErr != nil { + return errors.Wrap(updateErr, fmt.Sprintf("failed to update secret %s", secretName)) + } + + verifyErr := retry.OnError( + retry.DefaultRetry, + func(err error) bool { + return true + }, + func() error { + verifySecret := &corev1.Secret{} + if err := r.Client.Get(ctx, types.NamespacedName{ + Name: secretName, + Namespace: cluster.Namespace, + }, verifySecret); err != nil { + return err + } + + for labelKey, labelValue := range requiredLabels { + if existing, exists := verifySecret.Labels[labelKey]; !exists || existing != labelValue { + return errors.Errorf("secret %s label %s not yet propagated", secretName, labelKey) + } + } + + return nil + }) + + return errors.Wrap(verifyErr, "failed to update secret") +} + // reconcilePostgresUsersInPostgreSQL creates users inside of PostgreSQL and // sets their options and database access as specified. func (r *Reconciler) reconcilePostgresUsersInPostgreSQL( From 56185f4aaf91eac38a4e95de7a4475b7800d069d Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Thu, 17 Jul 2025 22:17:10 +0300 Subject: [PATCH 105/300] Release 2.7.0 op (#1219) --- Makefile | 60 +++++++++++++------ config/bundle/kustomization.yaml | 2 +- config/cw-bundle/kustomization.yaml | 2 +- config/manager/cluster/kustomization.yaml | 2 +- config/manager/namespace/kustomization.yaml | 2 +- deploy/bundle.yaml | 2 +- deploy/cr.yaml | 16 ++--- deploy/cw-bundle.yaml | 2 +- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 +-- e2e-tests/functions | 2 +- e2e-tests/run-release.csv | 1 - .../upgrade-minor/01-create-cluster.yaml | 10 +++- .../upgrade-minor/06-upgrade-cluster.yaml | 6 +- e2e-tests/vars.sh | 29 +++++++-- 16 files changed, 96 insertions(+), 52 deletions(-) diff --git a/Makefile b/Makefile index e0f98390fd..4f8bfce7dd 100644 --- a/Makefile +++ b/Makefile @@ -369,12 +369,36 @@ release-postgres-operator-image-labels: ##@ Percona # Default values if not already set +ifeq (undefined,$(origin REGISTRY_NAME)) + $(info REGISTRY_NAME is not set) +else ifeq (undefined,$(origin IMAGE)) + $(info IMAGE is not set) +else + IMAGE := $(REGISTRY_NAME)/$(IMAGE) + $(info Combined IMAGE: $(IMAGE)) +endif + NAME ?= percona-postgresql-operator VERSION ?= $(shell git rev-parse --abbrev-ref HEAD | sed -e 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]') ROOT_REPO ?= ${PWD} IMAGE_TAG_BASE ?= perconalab/$(NAME) IMAGE ?= $(IMAGE_TAG_BASE):$(VERSION) PGO_VERSION ?= $(shell git describe --tags) +REGISTRY_NAME ?= docker.io +REGISTRY_NAME_FULL = $(REGISTRY_NAME)/ + +generate: +ifneq (,$(filter percona/% perconalab/%,$(IMAGE))) + ifeq (,$(findstring docker.io/,$(IMAGE))) + IMAGE := $(REGISTRY_NAME_FULL)$(IMAGE) + $(info Updated IMAGE to: $(IMAGE)) + else + $(info IMAGE already qualified: $(IMAGE)) + endif +else + $(info Skipping: IMAGE does not match percona/perconalab) +endif +$(info $(IMAGE)) KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: ## Download kustomize locally if necessary. @@ -425,17 +449,17 @@ include e2e-tests/release_versions release: generate $(SED) -i \ -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(VERSION)/}" \ - -e "/^spec:/,/^ image:/{s#image: .*#image: $(IMAGE_POSTGRESQL17)#}" \ - -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(IMAGE_PGBOUNCER17)#}" \ - -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(IMAGE_BACKREST17)#}" \ - -e "/extensions:/,/image:/{s#image: .*#image: $(IMAGE_OPERATOR)#}" \ - -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(IMAGE_PMM3_CLIENT)#}" deploy/cr.yaml + -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_POSTGRESQL17)#}" \ + -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_PGBOUNCER17)#}" \ + -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_BACKREST17)#}" \ + -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_OPERATOR)#}" \ + -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_PMM3_CLIENT)#}" deploy/cr.yaml $(SED) -i -r "/Version *= \"[0-9]+\.[0-9]+\.[0-9]+\"$$/ s/[0-9]+\.[0-9]+\.[0-9]+/$(VERSION)/" pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go $(SED) -i \ - -e "/^spec:/,/^ image:/{s#image: .*#image: $(IMAGE_OPERATOR)#}" \ - -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(IMAGE_POSTGRESQL17)#}" \ - -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(IMAGE_PGBOUNCER17)#}" \ - -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(IMAGE_BACKREST17)#}" deploy/upgrade.yaml + -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_UPGRADE)#}" \ + -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(REGISTRY_NAME_FULL)$(IMAGE_POSTGRESQL17)#}" \ + -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(REGISTRY_NAME_FULL)$(IMAGE_PGBOUNCER17)#}" \ + -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(REGISTRY_NAME_FULL)$(IMAGE_BACKREST17)#}" deploy/upgrade.yaml # Prepare main branch after release MAJOR_VER := $(shell grep -oE "crVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+\.[0-9]+\.[0-9]+"|cut -d'.' -f1) @@ -444,14 +468,14 @@ NEXT_VER ?= $(MAJOR_VER).$$(($(MINOR_VER) + 1)).0 after-release: generate $(SED) -i \ -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(NEXT_VER)/}" \ - -e "/^spec:/,/^ image:/{s#image: .*#image: perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ - -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-pgbouncer#}" \ - -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-pgbackrest#}" \ - -e "/extensions:/,/image:/{s#image: .*#image: perconalab/percona-postgresql-operator:main#}" \ - -e "/^ pmm:/,/^ image:/{s#image: .*#image: perconalab/pmm-client:dev-latest#}" deploy/cr.yaml + -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ + -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ + -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" \ + -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ + -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/pmm-client:dev-latest#}" deploy/cr.yaml $(SED) -i -r "/Version *= \"[0-9]+\.[0-9]+\.[0-9]+\"$$/ s/[0-9]+\.[0-9]+\.[0-9]+/$(NEXT_VER)/" pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go $(SED) -i \ - -e "/^spec:/,/^ image:/{s#image: .*#image: perconalab/percona-postgresql-operator:main#}" \ - -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ - -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-pgbouncer#}" \ - -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-pgbackrest#}" deploy/upgrade.yaml + -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-upgrade#}" \ + -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ + -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ + -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" deploy/upgrade.yaml diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index 1f1bca6817..e9bc76684e 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -6,5 +6,5 @@ resources: - ../manager/namespace images: - name: postgres-operator - newName: percona/percona-postgresql-operator + newName: docker.io/percona/percona-postgresql-operator newTag: 2.7.0 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 2e58fb5dbc..c0892b7f43 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -7,5 +7,5 @@ resources: images: - name: postgres-operator - newName: percona/percona-postgresql-operator + newName: docker.io/percona/percona-postgresql-operator newTag: 2.7.0 diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index 46b272f528..64433133ad 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -8,5 +8,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: percona/percona-postgresql-operator + newName: docker.io/percona/percona-postgresql-operator newTag: 2.7.0 diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 274e45ceee..59df7f9ef8 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -9,5 +9,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: percona/percona-postgresql-operator + newName: docker.io/percona/percona-postgresql-operator newTag: 2.7.0 diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 036569b9b5..7d61e301f4 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -47581,7 +47581,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: percona/percona-postgresql-operator:2.7.0 + image: docker.io/percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index abab194bb2..a78c3ad9b5 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -11,7 +11,7 @@ metadata: spec: crVersion: 2.7.0 # initContainer: -# image: percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres +# image: docker.io/percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres + image: docker.io/percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -180,7 +180,7 @@ spec: - name: instance1 replicas: 3 # initContainer: -# image: perconalab/percona-postgresql-operator:main +# image: docker.io/percona/percona-postgresql-operator:2.7.0 # resources: # limits: # cpu: 2.0 @@ -304,7 +304,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: percona/percona-pgbouncer:1.24.1 + image: docker.io/percona/percona-pgbouncer:1.24.1 # exposeSuperusers: true # resources: # limits: @@ -394,9 +394,9 @@ spec: pgbackrest: # metadata: # labels: - image: percona/percona-pgbackrest:2.55.0 + image: docker.io/percona/percona-pgbackrest:2.55.0 # initContainer: -# image: perconalab/percona-postgresql-operator:main +# image: docker.io/percona/percona-postgresql-operator:2.7.0 # resources: # limits: # cpu: 2.0 @@ -585,7 +585,7 @@ spec: pmm: enabled: false - image: percona/pmm-client:3.2.0 + image: docker.io/percona/pmm-client:3.2.0 # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -619,7 +619,7 @@ spec: # - basebackup # extensions: -# image: percona/percona-postgresql-operator:2.7.0 +# image: docker.io/percona/percona-postgresql-operator:2.7.0 # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index a9ffe36c0f..75f01652d8 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -47579,7 +47579,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: percona/percona-postgresql-operator:2.7.0 + image: docker.io/percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 481d2a7d19..357d0bb001 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: percona/percona-postgresql-operator:2.7.0 + image: docker.io/percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 263b13c814..f238229a20 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: percona/percona-postgresql-operator:2.7.0 + image: docker.io/percona/percona-postgresql-operator:2.7.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 32deeeecf6..733d27bfbd 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: percona/percona-postgresql-operator:2.7.0-upgrade + image: docker.io/percona/percona-postgresql-operator:2.7.0-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres - toPgBouncerImage: percona/percona-pgbouncer:1.24.1 - toPgBackRestImage: percona/percona-pgbackrest:2.55.0 + toPostgresImage: docker.io/percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres + toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.24.1 + toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.55.0 diff --git a/e2e-tests/functions b/e2e-tests/functions index e156c004ea..e3b43dcce8 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -92,7 +92,7 @@ deploy_operator_gh() { curl -s "https://raw.githubusercontent.com/percona/percona-postgresql-operator/${git_tag}/deploy/${cw_prefix}operator.yaml" >"${TEMP_DIR}/${cw_prefix}operator_${git_tag}.yaml" - yq eval '.spec.template.spec.containers[0].image = "percona/percona-postgresql-operator:'${git_tag#v}'"' \ + yq eval '.spec.template.spec.containers[0].image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${git_tag#v}'"' \ "${TEMP_DIR}/${cw_prefix}operator_${git_tag}.yaml" \ | kubectl -n "${OPERATOR_NS:-$NAMESPACE}" apply -f - } diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 55e8d44061..6217656a38 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -5,7 +5,6 @@ demand-backup finalizers init-deploy major-upgrade -migration-backup-s3 monitoring monitoring-pmm3 one-pod diff --git a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml index ac31b4a330..4bda5fff9c 100644 --- a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml @@ -24,14 +24,18 @@ commands: fi echo $pg_ver >"${TEMP_DIR}/pg_ver.txt" + if [[ $OPENSHIFT ]]; then + $sed -E -i "s|^( *image: *)(.*)|\1${REGISTRY_NAME_FULL}\2|" ${TEMP_DIR}/cr_lower.yaml + fi + yq -i eval ' .metadata.name = "'${test_name}'" | .metadata.labels = {"e2e":"'${test_name}'"} | - .spec.image = "percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-postgres" | + .spec.image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-postgres" | .spec.postgresVersion = '$pg_ver' | - .spec.proxy.pgBouncer.image = "percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-pgbouncer" | + .spec.proxy.pgBouncer.image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-pgbouncer" | .spec.backups.pgbackrest.repos[0].schedules = null | - .spec.backups.pgbackrest.image = "percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-pgbackrest" | + .spec.backups.pgbackrest.image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-pgbackrest" | .spec.users += [{"name":"postgres","password":{"type":"AlphaNumeric"}}] | .spec.users += [{"name":"'${test_name}'","password":{"type":"AlphaNumeric"}}]' "${TEMP_DIR}/cr_lower.yaml" kubectl -n "${NAMESPACE}" apply -f "${TEMP_DIR}/cr_lower.yaml" diff --git a/e2e-tests/tests/upgrade-minor/06-upgrade-cluster.yaml b/e2e-tests/tests/upgrade-minor/06-upgrade-cluster.yaml index f43220c9ed..ac7393f344 100644 --- a/e2e-tests/tests/upgrade-minor/06-upgrade-cluster.yaml +++ b/e2e-tests/tests/upgrade-minor/06-upgrade-cluster.yaml @@ -13,9 +13,9 @@ commands: target_image_backrest=$IMAGE_BACKREST if [ "$pg_ver_lower" != "$PG_VER" ]; then - target_image_postgresql="perconalab/percona-postgresql-operator:main-ppg$pg_ver_lower-postgres" - target_image_pgbouncer="perconalab/percona-postgresql-operator:main-ppg$pg_ver_lower-pgbouncer" - target_image_backrest="perconalab/percona-postgresql-operator:main-ppg$pg_ver_lower-pgbackrest" + target_image_postgresql="${REGISTRY_NAME_FULL}perconalab/percona-postgresql-operator:main-ppg$pg_ver_lower-postgres" + target_image_pgbouncer="${REGISTRY_NAME_FULL}perconalab/percona-postgresql-operator:main-ppg$pg_ver_lower-pgbouncer" + target_image_backrest="${REGISTRY_NAME_FULL}perconalab/percona-postgresql-operator:main-ppg$pg_ver_lower-pgbackrest" fi cr_ver=$(yq '.spec.crVersion' $DEPLOY_DIR/cr.yaml) diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 47a3dd2cf6..1b3eb9b609 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -12,6 +12,12 @@ export TEMP_DIR="/tmp/kuttl/pg/${test_name}" export GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) export VERSION=${VERSION:-$(echo "${GIT_BRANCH}" | sed -e 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]')} +if command -v oc &>/dev/null; then + if oc get projects; then + export OPENSHIFT=4 + fi +fi + export IMAGE_BASE=${IMAGE_BASE:-"perconalab/percona-postgresql-operator"} export IMAGE=${IMAGE:-"${IMAGE_BASE}:${VERSION}"} export PG_VER="${PG_VER:-17}" @@ -28,13 +34,24 @@ export IMAGE_PMM3_SERVER=${IMAGE_PMM3_SERVER:-"perconalab/pmm-server:3-dev-lates export PGOV1_TAG=${PGOV1_TAG:-"1.4.0"} export PGOV1_VER=${PGOV1_VER:-"14"} +# Add 'docker.io' for images that are provided without registry +export REGISTRY_NAME="docker.io" +export REGISTRY_NAME_FULL="${REGISTRY_NAME}/" + +for var in $(printenv | grep -E '^IMAGE' | awk -F'=' '{print $1}'); do + var_value=$(eval "echo \$$var") + if [[ "$var_value" == docker.io/* ]]; then + continue + fi + if [[ "$var_value" == percona/* || "$var_value" == perconalab/* ]]; then + new_value="${REGISTRY_NAME_FULL}${var_value}" + export "$var=$new_value" + echo $var=$new_value + fi + echo $IMAGE +done + # shellcheck disable=SC2034 date=$(which gdate || which date) # shellcheck disable=SC2034 sed=$(which gsed || which sed) - -if command -v oc &>/dev/null; then - if oc get projects; then - export OPENSHIFT=4 - fi -fi From 2b721be58505d9565f4d194f9f605deff4f9547e Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Thu, 17 Jul 2025 16:26:02 -0300 Subject: [PATCH 106/300] Update pmm version in release_versions file --- e2e-tests/release_versions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/release_versions b/e2e-tests/release_versions index 80d860d66e..4e7b46b824 100644 --- a/e2e-tests/release_versions +++ b/e2e-tests/release_versions @@ -30,8 +30,8 @@ IMAGE_UPGRADE=percona/percona-postgresql-operator:2.7.0-upgrade IMAGE_PMM_CLIENT=percona/pmm-client:2.44.1 IMAGE_PMM_SERVER=percona/pmm-server:2.44.1 -IMAGE_PMM3_CLIENT=percona/pmm-client:3.2.0 -IMAGE_PMM3_SERVER=percona/pmm-server:3.2.0 +IMAGE_PMM3_CLIENT=percona/pmm-client:3.3.0 +IMAGE_PMM3_SERVER=percona/pmm-server:3.3.0 # Supported k8s versions GKE_MIN=1.30 From 5d629ca2bfa4f316d98b96091b887d425240b414 Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Fri, 18 Jul 2025 15:58:56 -0300 Subject: [PATCH 107/300] Revert images back to main after 2.7.0 release --- Makefile | 15 +++++++++++---- config/bundle/kustomization.yaml | 4 ++-- .../versionlabel_in_perconapgbackups.yaml | 2 +- .../versionlabel_in_perconapgclusters.yaml | 2 +- .../versionlabel_in_perconapgrestores.yaml | 2 +- .../versionlabel_in_perconapgupgrade.yaml | 2 +- config/cw-bundle/kustomization.yaml | 4 ++-- config/manager/cluster/kustomization.yaml | 4 ++-- config/manager/namespace/kustomization.yaml | 4 ++-- deploy/bundle.yaml | 10 +++++----- deploy/cr.yaml | 18 +++++++++--------- deploy/crd.yaml | 8 ++++---- deploy/cw-bundle.yaml | 10 +++++----- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 ++++---- e2e-tests/tests/init-deploy/05-assert.yaml | 12 ++++++------ .../tests/upgrade-consistency/01-assert.yaml | 2 +- .../upgrade-consistency/01-create-cluster.yaml | 2 +- .../tests/upgrade-consistency/02-assert.yaml | 2 +- .../upgrade-consistency/02-patch-cluster.yaml | 2 +- .../tests/upgrade-consistency/03-assert.yaml | 2 +- .../upgrade-consistency/03-patch-cluster.yaml | 2 +- .../tests/upgrade-minor/01-create-cluster.yaml | 13 +++++++++---- e2e-tests/vars.sh | 4 ++-- .../testdata/sidecar-resources-cr.yaml | 2 +- percona/version/version.txt | 2 +- 27 files changed, 77 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index 4f8bfce7dd..18305d77b8 100644 --- a/Makefile +++ b/Makefile @@ -462,20 +462,27 @@ release: generate -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(REGISTRY_NAME_FULL)$(IMAGE_BACKREST17)#}" deploy/upgrade.yaml # Prepare main branch after release -MAJOR_VER := $(shell grep -oE "crVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+\.[0-9]+\.[0-9]+"|cut -d'.' -f1) -MINOR_VER := $(shell grep -oE "crVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+\.[0-9]+\.[0-9]+"|cut -d'.' -f2) -NEXT_VER ?= $(MAJOR_VER).$$(($(MINOR_VER) + 1)).0 +CURRENT_VERSION := $(shell grep -oE "crVersion: [0-9]+\.[0-9]+\.[0-9]+" deploy/cr.yaml | grep -oE "[0-9]+\.[0-9]+\.[0-9]+") +MAJOR_VER := $(word 1,$(subst ., ,$(CURRENT_VERSION))) +MINOR_VER := $(word 2,$(subst ., ,$(CURRENT_VERSION))) +NEXT_VER := $(MAJOR_VER).$(shell expr $(MINOR_VER) + 1).0 +PREV1_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 1).0 +PREV2_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 2).0 after-release: generate + echo $(NEXT_VER) > percona/version/version.txt $(SED) -i \ -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(NEXT_VER)/}" \ -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" \ -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ - -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/pmm-client:dev-latest#}" deploy/cr.yaml + -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/pmm-client:dev-latest#}" deploy/cr.yaml percona/controller/testdata/sidecar-resources-cr.yaml $(SED) -i -r "/Version *= \"[0-9]+\.[0-9]+\.[0-9]+\"$$/ s/[0-9]+\.[0-9]+\.[0-9]+/$(NEXT_VER)/" pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go $(SED) -i \ -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-upgrade#}" \ -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" deploy/upgrade.yaml + $(SED) -i "s/$(PREV2_VERSION)/$(PREV1_VERSION)/g" e2e-tests/tests/upgrade-consistency/01-*.yaml + $(SED) -i "s/$(PREV1_VERSION)/$(CURRENT_VERSION)/g" e2e-tests/tests/upgrade-consistency/02-*.yaml + $(SED) -i "s/$(CURRENT_VERSION)/$(NEXT_VER)/g" e2e-tests/tests/upgrade-consistency/03-*.yaml e2e-tests/tests/init-deploy/05-assert.yaml \ No newline at end of file diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index e9bc76684e..90cf89956e 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -6,5 +6,5 @@ resources: - ../manager/namespace images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.7.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/crd/patches/versionlabel_in_perconapgbackups.yaml b/config/crd/patches/versionlabel_in_perconapgbackups.yaml index eccb519f33..d4c5958860 100644 --- a/config/crd/patches/versionlabel_in_perconapgbackups.yaml +++ b/config/crd/patches/versionlabel_in_perconapgbackups.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgbackups.pgv2.percona.com labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 diff --git a/config/crd/patches/versionlabel_in_perconapgclusters.yaml b/config/crd/patches/versionlabel_in_perconapgclusters.yaml index 1e510c760e..9ee2cce213 100644 --- a/config/crd/patches/versionlabel_in_perconapgclusters.yaml +++ b/config/crd/patches/versionlabel_in_perconapgclusters.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgclusters.pgv2.percona.com labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 diff --git a/config/crd/patches/versionlabel_in_perconapgrestores.yaml b/config/crd/patches/versionlabel_in_perconapgrestores.yaml index 49c0b499f1..9d4796443f 100644 --- a/config/crd/patches/versionlabel_in_perconapgrestores.yaml +++ b/config/crd/patches/versionlabel_in_perconapgrestores.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgrestores.pgv2.percona.com labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 diff --git a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml index 4f41858170..75d0fce2bb 100644 --- a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml +++ b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgupgrades.pgv2.percona.com labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index c0892b7f43..440d098731 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -7,5 +7,5 @@ resources: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.7.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index 64433133ad..6f8f4bf129 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -8,5 +8,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.7.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 59df7f9ef8..a57ff786e0 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -9,5 +9,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.7.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 95140606d5..2aef075e20 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -707,7 +707,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -19138,7 +19138,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -19238,7 +19238,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -47640,7 +47640,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.7.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 11db065230..82bb4399ac 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,9 +9,9 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: 2.7.0 + crVersion: 2.8.0 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: docker.io/percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres + image: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -182,7 +182,7 @@ spec: - name: instance1 replicas: 3 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.7.0 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -306,7 +306,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: docker.io/percona/percona-pgbouncer:1.24.1 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 # exposeSuperusers: true # resources: # limits: @@ -397,9 +397,9 @@ spec: pgbackrest: # metadata: # labels: - image: docker.io/percona/percona-pgbackrest:2.55.0 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.7.0 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -588,7 +588,7 @@ spec: pmm: enabled: false - image: docker.io/percona/pmm-client:3.2.0 + image: docker.io/perconalab/pmm-client:dev-latest # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -622,7 +622,7 @@ spec: # - basebackup # extensions: -# image: docker.io/percona/percona-postgresql-operator:2.7.0 +# image: docker.io/perconalab/percona-postgresql-operator:main # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 407ac4d2d9..3235df0e9e 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -707,7 +707,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -19138,7 +19138,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -19238,7 +19238,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 51dfb3bcf0..538a5cbb4b 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -707,7 +707,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -19138,7 +19138,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -19238,7 +19238,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.7.0 + pgv2.percona.com/version: v2.8.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -47638,7 +47638,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.7.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 357d0bb001..7861413845 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.7.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index f238229a20..c6c492333b 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.7.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 733d27bfbd..59ddf91d3b 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: docker.io/percona/percona-postgresql-operator:2.7.0-upgrade + image: docker.io/perconalab/percona-postgresql-operator:main-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: docker.io/percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres - toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.24.1 - toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.55.0 + toPostgresImage: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres + toPgBouncerImage: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 + toPgBackRestImage: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 diff --git a/e2e-tests/tests/init-deploy/05-assert.yaml b/e2e-tests/tests/init-deploy/05-assert.yaml index b4c0bde00d..246ab59daf 100644 --- a/e2e-tests/tests/init-deploy/05-assert.yaml +++ b/e2e-tests/tests/init-deploy/05-assert.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.7.0 + pgv2.percona.com/version: 2.8.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -81,7 +81,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.7.0 + pgv2.percona.com/version: 2.8.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -144,7 +144,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.7.0 + pgv2.percona.com/version: 2.8.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -168,7 +168,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.7.0 + pgv2.percona.com/version: 2.8.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -191,7 +191,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.7.0 + pgv2.percona.com/version: 2.8.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" @@ -214,7 +214,7 @@ spec: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.7.0 + pgv2.percona.com/version: 2.8.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" diff --git a/e2e-tests/tests/upgrade-consistency/01-assert.yaml b/e2e-tests/tests/upgrade-consistency/01-assert.yaml index c5baa6caef..60b019bcef 100644 --- a/e2e-tests/tests/upgrade-consistency/01-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-assert.yaml @@ -122,7 +122,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.5.0 + crVersion: 2.6.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml index d791e6bf18..f7446f8210 100644 --- a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml @@ -10,6 +10,6 @@ commands: get_cr \ | yq eval ' - .spec.crVersion="2.5.0"' - \ + .spec.crVersion="2.6.0"' - \ | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:main-ppg$PG_VER-pgbackrest\"" - \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/upgrade-consistency/02-assert.yaml b/e2e-tests/tests/upgrade-consistency/02-assert.yaml index 85805ada42..4bce8de813 100644 --- a/e2e-tests/tests/upgrade-consistency/02-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.6.0 + crVersion: 2.7.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index 3c2c0cb7b6..2d3cb25d26 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -10,7 +10,7 @@ commands: get_cr \ | yq eval ' - .spec.crVersion="2.6.0"' - \ + .spec.crVersion="2.7.0"' - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 diff --git a/e2e-tests/tests/upgrade-consistency/03-assert.yaml b/e2e-tests/tests/upgrade-consistency/03-assert.yaml index 2475789519..bcc9f45111 100644 --- a/e2e-tests/tests/upgrade-consistency/03-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.7.0 + crVersion: 2.8.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 2d27389b20..ea48c5a48d 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -10,7 +10,7 @@ commands: get_cr \ | yq eval ' - .spec.crVersion="2.7.0"' - \ + .spec.crVersion="2.8.0"' - \ | yq eval ".spec.backups.pgbackrest.image=\"$IMAGE_BACKREST\"" - \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml index 4bda5fff9c..358a147dac 100644 --- a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml @@ -17,7 +17,7 @@ commands: pg_exists=0 pg_exists=$(curl -s https://check.percona.com/versions/v1/pg-operator/${lower_ver} | jq '.versions[].matrix.postgresql | with_entries(select(.key | startswith("'$pg_ver'"))) | length') # if the lower version of operator doesn't have new PG version we will use lower PG version - # but in that case not the intended targer PG database image will be tested + # but in that case not the intended target PG database image will be tested # (this should happen once a year on major PG version release, but only for this latest version) if [ $pg_exists -eq 0 ]; then pg_ver=$((pg_ver - 1)) @@ -28,14 +28,19 @@ commands: $sed -E -i "s|^( *image: *)(.*)|\1${REGISTRY_NAME_FULL}\2|" ${TEMP_DIR}/cr_lower.yaml fi + lower_ver_images=$(curl -s https://raw.githubusercontent.com/percona/percona-postgresql-operator/refs/tags/v${lower_ver}/e2e-tests/release_versions) + backrest_image=$(echo "$lower_ver_images" | grep BACKREST${pg_ver} | cut -d'=' -f2 ) + pgbouncer_image=$(echo "$lower_ver_images" | grep PGBOUNCER${pg_ver} | cut -d'=' -f2 ) + postgres_image=$(echo "$lower_ver_images" | grep POSTGRESQL${pg_ver} | cut -d'=' -f2 ) + yq -i eval ' .metadata.name = "'${test_name}'" | .metadata.labels = {"e2e":"'${test_name}'"} | - .spec.image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-postgres" | + .spec.image = "'${REGISTRY_NAME_FULL}''${postgres_image}'" | .spec.postgresVersion = '$pg_ver' | - .spec.proxy.pgBouncer.image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-pgbouncer" | + .spec.proxy.pgBouncer.image = "'${REGISTRY_NAME_FULL}''${pgbouncer_image}'" | .spec.backups.pgbackrest.repos[0].schedules = null | - .spec.backups.pgbackrest.image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${lower_ver}'-ppg'$pg_ver'-pgbackrest" | + .spec.backups.pgbackrest.image = "'${REGISTRY_NAME_FULL}''${backrest_image}'" | .spec.users += [{"name":"postgres","password":{"type":"AlphaNumeric"}}] | .spec.users += [{"name":"'${test_name}'","password":{"type":"AlphaNumeric"}}]' "${TEMP_DIR}/cr_lower.yaml" kubectl -n "${NAMESPACE}" apply -f "${TEMP_DIR}/cr_lower.yaml" diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 1b3eb9b609..c6ea36bead 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -40,10 +40,10 @@ export REGISTRY_NAME_FULL="${REGISTRY_NAME}/" for var in $(printenv | grep -E '^IMAGE' | awk -F'=' '{print $1}'); do var_value=$(eval "echo \$$var") - if [[ "$var_value" == docker.io/* ]]; then + if [[ $var_value == docker.io/* ]]; then continue fi - if [[ "$var_value" == percona/* || "$var_value" == perconalab/* ]]; then + if [[ $var_value == percona/* || $var_value == perconalab/* ]]; then new_value="${REGISTRY_NAME_FULL}${var_value}" export "$var=$new_value" echo $var=$new_value diff --git a/percona/controller/testdata/sidecar-resources-cr.yaml b/percona/controller/testdata/sidecar-resources-cr.yaml index 56adb71a51..1c137a6ead 100644 --- a/percona/controller/testdata/sidecar-resources-cr.yaml +++ b/percona/controller/testdata/sidecar-resources-cr.yaml @@ -4,7 +4,7 @@ kind: PerconaPGCluster metadata: name: cluster1 spec: - crVersion: 2.7.0 + crVersion: 2.8.0 image: perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always diff --git a/percona/version/version.txt b/percona/version/version.txt index 24ba9a38de..834f262953 100644 --- a/percona/version/version.txt +++ b/percona/version/version.txt @@ -1 +1 @@ -2.7.0 +2.8.0 From 3179fa8c67d38b5daa61d8a5bfb359c9859c988e Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 23 Jul 2025 11:04:59 +0300 Subject: [PATCH 108/300] K8SPG-611 when cr version is different than version, build init container image instead of using the operator image (#1236) --- e2e-tests/functions | 3 ++- percona/k8s/util.go | 24 +++++++++++++++++++++++- percona/k8s/util_test.go | 13 +++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 25cabe4c15..1b0290d79d 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -92,7 +92,8 @@ deploy_operator_gh() { curl -s "https://raw.githubusercontent.com/percona/percona-postgresql-operator/${git_tag}/deploy/${cw_prefix}operator.yaml" >"${TEMP_DIR}/${cw_prefix}operator_${git_tag}.yaml" - yq eval '.spec.template.spec.containers[0].image = "'${REGISTRY_NAME_FULL}'percona/percona-postgresql-operator:'${git_tag#v}'"' \ + local docker_hub_org=$(echo "$IMAGE" | sed -E 's|(.*/)?([^/]+)/[^/]+(:.*)?|\2|') + yq eval '.spec.template.spec.containers[0].image = "'${REGISTRY_NAME_FULL}''$docker_hub_org'/percona-postgresql-operator:'${git_tag#v}'"' \ "${TEMP_DIR}/${cw_prefix}operator_${git_tag}.yaml" \ | kubectl -n "${OPERATOR_NS:-$NAMESPACE}" apply -f - } diff --git a/percona/k8s/util.go b/percona/k8s/util.go index be89708851..3133d9df4e 100644 --- a/percona/k8s/util.go +++ b/percona/k8s/util.go @@ -17,6 +17,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/percona/percona-postgresql-operator/percona/naming" + "github.com/percona/percona-postgresql-operator/percona/version" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -87,7 +88,28 @@ func InitImage(ctx context.Context, cl client.Reader, cluster *v1beta1.PostgresC if cluster != nil && cluster.Spec.InitContainer != nil && len(cluster.Spec.InitContainer.Image) > 0 { return cluster.Spec.InitContainer.Image, nil } - return operatorImage(ctx, cl) + + operatorImage, err := operatorImage(ctx, cl) + if err != nil { + return "", errors.Wrap(err, "get operator image") + } + + imageName := operatorImage + + if cluster == nil { + return imageName, nil + } + + crVersion, ok := cluster.Labels[v1beta1.LabelVersion] + if !ok || crVersion == "" { + return imageName, nil + } + + if cluster.CompareVersion(version.Version()) != 0 { + imageName = strings.Split(operatorImage, ":")[0] + ":" + crVersion + } + + return imageName, nil } func operatorImage(ctx context.Context, cl client.Reader) (string, error) { diff --git a/percona/k8s/util_test.go b/percona/k8s/util_test.go index 714239d273..1c27d26275 100644 --- a/percona/k8s/util_test.go +++ b/percona/k8s/util_test.go @@ -267,6 +267,19 @@ func TestInitImage(t *testing.T) { getPGBackrestComponent, "operator-image", }, + { + "pgbackrest not specified init image with different versions", + func() *v1beta1.PostgresCluster { + cr := crunchyCr.DeepCopy() + + oldVersion := "1.2.0" + + cr.Labels = map[string]string{v1beta1.LabelVersion: oldVersion} + return cr + }, + getPGBackrestComponent, + "operator-image:1.2.0", + }, { "pgbackrest general init image", func() *v1beta1.PostgresCluster { From e3dadcf98487e95ee20b712d3ccf4b820a5d8438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valmira=20Nogueira=20Corr=C3=AAa?= Date: Wed, 23 Jul 2025 07:02:36 -0300 Subject: [PATCH 109/300] K8SPG-820 - Introduce a collation mismatch check (#1234) * Add collation mismatch check * Add end of file lines * Skip verification by default and improve failure message --------- Co-authored-by: Viacheslav Sarzhan --- .../09-check-collation-mismatch.yaml | 23 +++++++++++++++++++ .../upgrade-minor/09-collation-mismatch.sql | 8 +++++++ e2e-tests/vars.sh | 3 +++ 3 files changed, 34 insertions(+) create mode 100644 e2e-tests/tests/upgrade-minor/09-check-collation-mismatch.yaml create mode 100644 e2e-tests/tests/upgrade-minor/09-collation-mismatch.sql diff --git a/e2e-tests/tests/upgrade-minor/09-check-collation-mismatch.yaml b/e2e-tests/tests/upgrade-minor/09-check-collation-mismatch.yaml new file mode 100644 index 0000000000..cec7b3de2f --- /dev/null +++ b/e2e-tests/tests/upgrade-minor/09-check-collation-mismatch.yaml @@ -0,0 +1,23 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: +- script: |- + set -o errexit + set -o xtrace + + source ../../functions + + if [[ "${SKIP_TEST_WARNINGS}" == "true" ]]; then + echo "Collation mismatch verification skipped." + exit 0 + fi + + # Replace new lines, whitespaces and quotes + query_mismatch=$(<09-collation-mismatch.sql tr '\n' ' ' | sed "s/'/'\\\\''/g" | sed 's/ */ /g') + data=$(run_psql_local "$query_mismatch" "postgres:$(get_psql_user_pass upgrade-minor-pguser-postgres)@$(get_psql_user_host upgrade-minor-pguser-postgres)") + + if [[ "$data" == *"Collection mismatch detected"* ]]; then + echo "Collation mismatch detected after minor upgrade. Ensure that the necessary Release Notes documentation is in place. For further details, refer to: https://perconadev.atlassian.net/browse/K8SPG-820." + exit 1 + fi diff --git a/e2e-tests/tests/upgrade-minor/09-collation-mismatch.sql b/e2e-tests/tests/upgrade-minor/09-collation-mismatch.sql new file mode 100644 index 0000000000..f22b3f0ed3 --- /dev/null +++ b/e2e-tests/tests/upgrade-minor/09-collation-mismatch.sql @@ -0,0 +1,8 @@ +SELECT + 'Collection mismatch detected: current_version=' || pg_collation_actual_version(c.oid) || + ', db_version=' || c.collversion AS mismatch_message +FROM pg_database d +JOIN pg_collation c + ON REPLACE(d.datcollate, '-', '') = REPLACE(c.collcollate, '-', '') +WHERE d.datname = current_database() + AND pg_collation_actual_version(c.oid) IS DISTINCT FROM c.collversion; diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index b5199a6418..185eeda8e9 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -12,6 +12,9 @@ export TEMP_DIR="/tmp/kuttl/pg/${test_name}" export GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) export VERSION=${VERSION:-$(echo "${GIT_BRANCH}" | sed -e 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]')} +# Skip warning checks used for documentation by default +export SKIP_TEST_WARNINGS=${SKIP_TEST_WARNINGS:-"true"} + if command -v oc &>/dev/null; then if oc get projects; then export OPENSHIFT=4 From 74b1d76d0e23926385b65a595481e1b84c8c0777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 23 Jul 2025 13:03:17 +0300 Subject: [PATCH 110/300] K8SPG-460: Mount hugepage volumes (#1230) Co-authored-by: Viacheslav Sarzhan --- internal/postgres/huge_pages.go | 32 +++- internal/postgres/reconcile.go | 38 ++++ internal/postgres/reconcile_test.go | 276 ++++++++++++++++++++++++++++ 3 files changed, 341 insertions(+), 5 deletions(-) diff --git a/internal/postgres/huge_pages.go b/internal/postgres/huge_pages.go index 94e3cdfd57..05f0cc8e51 100644 --- a/internal/postgres/huge_pages.go +++ b/internal/postgres/huge_pages.go @@ -5,8 +5,6 @@ package postgres import ( - "strings" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -24,12 +22,12 @@ func SetHugePages(cluster *v1beta1.PostgresCluster, pgParameters *Parameters) { } } -// This helper function checks to see if a huge_pages value greater than zero has +// This helper function checks to see if a hugepages-2Mi value greater than zero has // been set in any of the PostgresCluster's instances' resource specs -func HugePagesRequested(cluster *v1beta1.PostgresCluster) bool { +func HugePages2MiRequested(cluster *v1beta1.PostgresCluster) bool { for _, instance := range cluster.Spec.InstanceSets { for resourceName := range instance.Resources.Limits { - if strings.HasPrefix(resourceName.String(), corev1.ResourceHugePagesPrefix) { + if resourceName == corev1.ResourceHugePagesPrefix+"2Mi" { resourceQuantity := instance.Resources.Limits.Name(resourceName, resource.BinarySI) if resourceQuantity != nil && resourceQuantity.Value() > 0 { @@ -41,3 +39,27 @@ func HugePagesRequested(cluster *v1beta1.PostgresCluster) bool { return false } + +// This helper function checks to see if a hugepages-1Gi value greater than zero has +// been set in any of the PostgresCluster's instances' resource specs +func HugePages1GiRequested(cluster *v1beta1.PostgresCluster) bool { + for _, instance := range cluster.Spec.InstanceSets { + for resourceName := range instance.Resources.Limits { + if resourceName == corev1.ResourceHugePagesPrefix+"1Gi" { + resourceQuantity := instance.Resources.Limits.Name(resourceName, resource.BinarySI) + + if resourceQuantity != nil && resourceQuantity.Value() > 0 { + return true + } + } + } + } + + return false +} + +// This helper function checks to see if a huge_pages value greater than zero has +// been set in any of the PostgresCluster's instances' resource specs +func HugePagesRequested(cluster *v1beta1.PostgresCluster) bool { + return HugePages2MiRequested(cluster) || HugePages1GiRequested(cluster) +} diff --git a/internal/postgres/reconcile.go b/internal/postgres/reconcile.go index 6a1dba8ad5..efcbba51e6 100644 --- a/internal/postgres/reconcile.go +++ b/internal/postgres/reconcile.go @@ -157,6 +157,22 @@ func InstancePod(ctx context.Context, dataVolumeMount, downwardAPIVolumeMount, } + + if HugePages2MiRequested(inCluster) { + dbContainerMounts = append(dbContainerMounts, corev1.VolumeMount{ + + Name: "hugepage-2mi", + MountPath: "/hugepages-2Mi", + }) + } + + if HugePages1GiRequested(inCluster) { + dbContainerMounts = append(dbContainerMounts, corev1.VolumeMount{ + Name: "hugepage-1gi", + MountPath: "/hugepages-1Gi", + }) + } + dbContainerMounts = append(dbContainerMounts, inInstanceSpec.VolumeMounts...) container := corev1.Container{ @@ -221,6 +237,28 @@ func InstancePod(ctx context.Context, downwardAPIVolume, } + if HugePages2MiRequested(inCluster) { + outInstancePod.Volumes = append(outInstancePod.Volumes, corev1.Volume{ + Name: "hugepage-2mi", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + Medium: corev1.StorageMediumHugePagesPrefix + "2Mi", + }, + }, + }) + } + + if HugePages1GiRequested(inCluster) { + outInstancePod.Volumes = append(outInstancePod.Volumes, corev1.Volume{ + Name: "hugepage-1gi", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + Medium: corev1.StorageMediumHugePagesPrefix + "1Gi", + }, + }, + }) + } + // If `TablespaceVolumes` FeatureGate is enabled, `inTablespaceVolumes` may not be nil. // In that case, add any tablespace volumes to the pod, and // add volumeMounts to the database and startup containers diff --git a/internal/postgres/reconcile_test.go b/internal/postgres/reconcile_test.go index 2cd1e2b933..dc85578444 100644 --- a/internal/postgres/reconcile_test.go +++ b/internal/postgres/reconcile_test.go @@ -708,6 +708,282 @@ volumes: assert.DeepEqual(t, pod.InitContainers[0].Command[4:], []string{"startup", "11", "/pgwal/pg11_wal", "/pgdata/pgbackrest/log"}) }) + + t.Run("WithHugepages2Mi", func(t *testing.T) { + clusterWithHugepages2Mi := cluster.DeepCopy() + clusterWithHugepages2Mi.Spec.InstanceSets = []v1beta1.PostgresInstanceSetSpec{ + { + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("4Gi"), + corev1.ResourceHugePagesPrefix + "2Mi": resource.MustParse("2Gi"), + }, + }, + }, + } + + pod := new(corev1.PodSpec) + InstancePod(ctx, clusterWithHugepages2Mi, instance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, nil, pod) + + assert.Assert(t, cmp.MarshalMatches(pod.Volumes, ` +- name: cert-volume + projected: + defaultMode: 384 + sources: + - secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + name: srv-secret + - secret: + items: + - key: tls.crt + path: replication/tls.crt + - key: tls.key + path: replication/tls.key + name: repl-secret +- name: postgres-data + persistentVolumeClaim: + claimName: datavol +- downwardAPI: + items: + - path: cpu_limit + resourceFieldRef: + containerName: database + divisor: 1m + resource: limits.cpu + - path: cpu_request + resourceFieldRef: + containerName: database + divisor: 1m + resource: requests.cpu + - path: mem_limit + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: limits.memory + - path: mem_request + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: requests.memory + - fieldRef: + apiVersion: v1 + fieldPath: metadata.labels + path: labels + - fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations + path: annotations + name: database-containerinfo +- emptyDir: + medium: HugePages-2Mi + name: hugepage-2mi + `), "expected HugePages-2Mi volume") + + assert.Assert(t, cmp.MarshalMatches(pod.Containers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- mountPath: /hugepages-2Mi + name: hugepage-2mi`), "expected hugepage mount in %q container", pod.Containers[0].Name) + }) + + t.Run("WithHugepages1Gi", func(t *testing.T) { + clusterWithHugepages1Gi := cluster.DeepCopy() + clusterWithHugepages1Gi.Spec.InstanceSets = []v1beta1.PostgresInstanceSetSpec{ + { + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("4Gi"), + corev1.ResourceHugePagesPrefix + "1Gi": resource.MustParse("2Gi"), + }, + }, + }, + } + + pod := new(corev1.PodSpec) + InstancePod(ctx, clusterWithHugepages1Gi, instance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, nil, pod) + + assert.Assert(t, cmp.MarshalMatches(pod.Volumes, ` +- name: cert-volume + projected: + defaultMode: 384 + sources: + - secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + name: srv-secret + - secret: + items: + - key: tls.crt + path: replication/tls.crt + - key: tls.key + path: replication/tls.key + name: repl-secret +- name: postgres-data + persistentVolumeClaim: + claimName: datavol +- downwardAPI: + items: + - path: cpu_limit + resourceFieldRef: + containerName: database + divisor: 1m + resource: limits.cpu + - path: cpu_request + resourceFieldRef: + containerName: database + divisor: 1m + resource: requests.cpu + - path: mem_limit + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: limits.memory + - path: mem_request + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: requests.memory + - fieldRef: + apiVersion: v1 + fieldPath: metadata.labels + path: labels + - fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations + path: annotations + name: database-containerinfo +- emptyDir: + medium: HugePages-1Gi + name: hugepage-1gi + `), "expected HugePages-1Gi volume") + + assert.Assert(t, cmp.MarshalMatches(pod.Containers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- mountPath: /hugepages-1Gi + name: hugepage-1gi`), "expected hugepage mount in %q container", pod.Containers[0].Name) + }) + + t.Run("WithHugepages", func(t *testing.T) { + clusterWithHugepages := cluster.DeepCopy() + clusterWithHugepages.Spec.InstanceSets = []v1beta1.PostgresInstanceSetSpec{ + { + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceMemory: resource.MustParse("4Gi"), + corev1.ResourceHugePagesPrefix + "2Mi": resource.MustParse("2Gi"), + corev1.ResourceHugePagesPrefix + "1Gi": resource.MustParse("2Gi"), + }, + }, + }, + } + + pod := new(corev1.PodSpec) + InstancePod(ctx, clusterWithHugepages, instance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, nil, pod) + + assert.Assert(t, cmp.MarshalMatches(pod.Volumes, ` +- name: cert-volume + projected: + defaultMode: 384 + sources: + - secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + name: srv-secret + - secret: + items: + - key: tls.crt + path: replication/tls.crt + - key: tls.key + path: replication/tls.key + name: repl-secret +- name: postgres-data + persistentVolumeClaim: + claimName: datavol +- downwardAPI: + items: + - path: cpu_limit + resourceFieldRef: + containerName: database + divisor: 1m + resource: limits.cpu + - path: cpu_request + resourceFieldRef: + containerName: database + divisor: 1m + resource: requests.cpu + - path: mem_limit + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: limits.memory + - path: mem_request + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: requests.memory + - fieldRef: + apiVersion: v1 + fieldPath: metadata.labels + path: labels + - fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations + path: annotations + name: database-containerinfo +- emptyDir: + medium: HugePages-2Mi + name: hugepage-2mi +- emptyDir: + medium: HugePages-1Gi + name: hugepage-1gi + `), "expected HugePages-2Mi and HugePages-1Gi volumes") + + assert.Assert(t, cmp.MarshalMatches(pod.Containers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- mountPath: /hugepages-2Mi + name: hugepage-2mi +- mountPath: /hugepages-1Gi + name: hugepage-1gi`), "expected hugepage mounts in %q container", pod.Containers[0].Name) + }) } func TestPodSecurityContext(t *testing.T) { From f810ad4da2a604d275fa9f85de765bba01281ad2 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Wed, 23 Jul 2025 13:08:12 +0300 Subject: [PATCH 111/300] WIP: set affinity for `patroni-version-check` pod (#1229) Co-authored-by: Viacheslav Sarzhan --- percona/controller/pgcluster/controller.go | 1 + .../controller/pgcluster/controller_test.go | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index ed0242f0c1..a30f4b887d 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -442,6 +442,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, }, }, SecurityContext: cr.Spec.InstanceSets[0].SecurityContext, + Affinity: cr.Spec.InstanceSets[0].Affinity, TerminationGracePeriodSeconds: ptr.To(int64(5)), ImagePullSecrets: cr.Spec.ImagePullSecrets, Resources: &corev1.ResourceRequirements{ diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 86b8a35ab4..46cf128d9b 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -1613,6 +1613,15 @@ var _ = Describe("patroni version check", Ordered, func() { cr2.Spec.InstanceSets[0].SecurityContext = &corev1.PodSecurityContext{ RunAsUser: &uid, } + cr2.Spec.InstanceSets[0].Affinity = &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []corev1.PreferredSchedulingTerm{ + { + Weight: int32(1), + }, + }, + }, + } cr2.Spec.ImagePullSecrets = []corev1.LocalObjectReference{ {Name: "test-pull-secret"}, } @@ -1683,10 +1692,20 @@ var _ = Describe("patroni version check", Ordered, func() { expectedImagePullSecrets := []corev1.LocalObjectReference{ {Name: "test-pull-secret"}, } + expectedAffinity := &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []corev1.PreferredSchedulingTerm{ + { + Weight: int32(1), + }, + }, + }, + } Expect(pod.Spec.SecurityContext).To(Equal(expectedSecurityContext)) Expect(pod.Spec.TerminationGracePeriodSeconds).To(Equal(ptr.To(int64(5)))) Expect(pod.Spec.ImagePullSecrets).To(Equal(expectedImagePullSecrets)) + Expect(pod.Spec.Affinity).To(Equal(expectedAffinity)) }) It("should preserve existing patroni version in annotation", func() { From cb78b6266d3b53cbae563048260af74f8e312106 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 23 Jul 2025 12:10:02 +0200 Subject: [PATCH 112/300] K8SPG-748 update statuses (#1220) * K8SPG-748 update statuses * update status for patroni and pgbackrest * update test * update tests * delete unused * update status naming * fix image --------- Co-authored-by: Viacheslav Sarzhan --- .../pgv2.percona.com_perconapgclusters.yaml | 221 +++++++++++++++++- .../pgv2.percona.com_perconapgclusters.yaml | 221 +++++++++++++++++- deploy/bundle.yaml | 221 +++++++++++++++++- deploy/crd.yaml | 221 +++++++++++++++++- deploy/cw-bundle.yaml | 221 +++++++++++++++++- e2e-tests/tests/demand-backup/01-assert.yaml | 6 + e2e-tests/tests/demand-backup/18-assert.yaml | 28 +++ percona/controller/pgcluster/controller.go | 8 +- .../controller/pgcluster/controller_test.go | 6 +- percona/controller/pgcluster/status.go | 52 ++++- percona/postgres/common.go | 2 +- .../v2/perconapgcluster_types.go | 16 +- .../v2/zz_generated.deepcopy.go | 26 +++ 13 files changed, 1229 insertions(+), 20 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 91966db202..87d4c141b5 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -18376,8 +18376,225 @@ spec: observedGeneration: format: int64 type: integer - patroniVersion: - type: string + patroni: + properties: + status: + properties: + switchover: + description: Tracks the execution of the switchover requests. + type: string + switchoverTimeline: + description: Tracks the current timeline during switchovers + format: int64 + type: integer + systemIdentifier: + description: The PostgreSQL system identifier reported by + Patroni. + type: string + type: object + version: + type: string + type: object + pgbackrest: + description: Status information for pgBackRest + properties: + manualBackup: + description: Status information for manual backups + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + repoHost: + description: Status information for the pgBackRest dedicated repository + host + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + ready: + description: Whether or not the pgBackRest repository host + is ready for use + type: boolean + type: object + repos: + description: Status information for pgBackRest repositories + items: + description: RepoStatus the status of a pgBackRest repository + properties: + bound: + description: Whether or not the pgBackRest repository PersistentVolumeClaim + is bound to a volume + type: boolean + name: + description: The name of the pgBackRest repository + type: string + replicaCreateBackupComplete: + description: |- + ReplicaCreateBackupReady indicates whether a backup exists in the repository as needed + to bootstrap replicas. + type: boolean + repoOptionsHash: + description: |- + A hash of the required fields in the spec for defining an Azure, GCS or S3 repository, + Utilized to detect changes to these fields and then execute pgBackRest stanza-create + commands accordingly. + type: string + stanzaCreated: + description: Specifies whether or not a stanza has been + successfully created for the repository + type: boolean + volume: + description: The name of the volume the containing the pgBackRest + repository + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Status information for in-place restores + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + scheduledBackups: + description: Status information for scheduled backups + items: + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + cronJobName: + description: The name of the associated pgBackRest scheduled + backup CronJob + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + repo: + description: The name of the associated pgBackRest repository + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + type: + description: The pgBackRest backup type for this Job + type: string + type: object + type: array + type: object pgbouncer: properties: ready: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 882ca6883d..11d5842c20 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -18783,8 +18783,225 @@ spec: observedGeneration: format: int64 type: integer - patroniVersion: - type: string + patroni: + properties: + status: + properties: + switchover: + description: Tracks the execution of the switchover requests. + type: string + switchoverTimeline: + description: Tracks the current timeline during switchovers + format: int64 + type: integer + systemIdentifier: + description: The PostgreSQL system identifier reported by + Patroni. + type: string + type: object + version: + type: string + type: object + pgbackrest: + description: Status information for pgBackRest + properties: + manualBackup: + description: Status information for manual backups + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + repoHost: + description: Status information for the pgBackRest dedicated repository + host + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + ready: + description: Whether or not the pgBackRest repository host + is ready for use + type: boolean + type: object + repos: + description: Status information for pgBackRest repositories + items: + description: RepoStatus the status of a pgBackRest repository + properties: + bound: + description: Whether or not the pgBackRest repository PersistentVolumeClaim + is bound to a volume + type: boolean + name: + description: The name of the pgBackRest repository + type: string + replicaCreateBackupComplete: + description: |- + ReplicaCreateBackupReady indicates whether a backup exists in the repository as needed + to bootstrap replicas. + type: boolean + repoOptionsHash: + description: |- + A hash of the required fields in the spec for defining an Azure, GCS or S3 repository, + Utilized to detect changes to these fields and then execute pgBackRest stanza-create + commands accordingly. + type: string + stanzaCreated: + description: Specifies whether or not a stanza has been + successfully created for the repository + type: boolean + volume: + description: The name of the volume the containing the pgBackRest + repository + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Status information for in-place restores + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + scheduledBackups: + description: Status information for scheduled backups + items: + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + cronJobName: + description: The name of the associated pgBackRest scheduled + backup CronJob + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + repo: + description: The name of the associated pgBackRest repository + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + type: + description: The pgBackRest backup type for this Job + type: string + type: object + type: array + type: object pgbouncer: properties: ready: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 857c191a46..ae1a32b774 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -19080,8 +19080,225 @@ spec: observedGeneration: format: int64 type: integer - patroniVersion: - type: string + patroni: + properties: + status: + properties: + switchover: + description: Tracks the execution of the switchover requests. + type: string + switchoverTimeline: + description: Tracks the current timeline during switchovers + format: int64 + type: integer + systemIdentifier: + description: The PostgreSQL system identifier reported by + Patroni. + type: string + type: object + version: + type: string + type: object + pgbackrest: + description: Status information for pgBackRest + properties: + manualBackup: + description: Status information for manual backups + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + repoHost: + description: Status information for the pgBackRest dedicated repository + host + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + ready: + description: Whether or not the pgBackRest repository host + is ready for use + type: boolean + type: object + repos: + description: Status information for pgBackRest repositories + items: + description: RepoStatus the status of a pgBackRest repository + properties: + bound: + description: Whether or not the pgBackRest repository PersistentVolumeClaim + is bound to a volume + type: boolean + name: + description: The name of the pgBackRest repository + type: string + replicaCreateBackupComplete: + description: |- + ReplicaCreateBackupReady indicates whether a backup exists in the repository as needed + to bootstrap replicas. + type: boolean + repoOptionsHash: + description: |- + A hash of the required fields in the spec for defining an Azure, GCS or S3 repository, + Utilized to detect changes to these fields and then execute pgBackRest stanza-create + commands accordingly. + type: string + stanzaCreated: + description: Specifies whether or not a stanza has been + successfully created for the repository + type: boolean + volume: + description: The name of the volume the containing the pgBackRest + repository + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Status information for in-place restores + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + scheduledBackups: + description: Status information for scheduled backups + items: + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + cronJobName: + description: The name of the associated pgBackRest scheduled + backup CronJob + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + repo: + description: The name of the associated pgBackRest repository + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + type: + description: The pgBackRest backup type for this Job + type: string + type: object + type: array + type: object pgbouncer: properties: ready: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index aecefd1073..a08e9c33ac 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -19080,8 +19080,225 @@ spec: observedGeneration: format: int64 type: integer - patroniVersion: - type: string + patroni: + properties: + status: + properties: + switchover: + description: Tracks the execution of the switchover requests. + type: string + switchoverTimeline: + description: Tracks the current timeline during switchovers + format: int64 + type: integer + systemIdentifier: + description: The PostgreSQL system identifier reported by + Patroni. + type: string + type: object + version: + type: string + type: object + pgbackrest: + description: Status information for pgBackRest + properties: + manualBackup: + description: Status information for manual backups + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + repoHost: + description: Status information for the pgBackRest dedicated repository + host + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + ready: + description: Whether or not the pgBackRest repository host + is ready for use + type: boolean + type: object + repos: + description: Status information for pgBackRest repositories + items: + description: RepoStatus the status of a pgBackRest repository + properties: + bound: + description: Whether or not the pgBackRest repository PersistentVolumeClaim + is bound to a volume + type: boolean + name: + description: The name of the pgBackRest repository + type: string + replicaCreateBackupComplete: + description: |- + ReplicaCreateBackupReady indicates whether a backup exists in the repository as needed + to bootstrap replicas. + type: boolean + repoOptionsHash: + description: |- + A hash of the required fields in the spec for defining an Azure, GCS or S3 repository, + Utilized to detect changes to these fields and then execute pgBackRest stanza-create + commands accordingly. + type: string + stanzaCreated: + description: Specifies whether or not a stanza has been + successfully created for the repository + type: boolean + volume: + description: The name of the volume the containing the pgBackRest + repository + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Status information for in-place restores + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + scheduledBackups: + description: Status information for scheduled backups + items: + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + cronJobName: + description: The name of the associated pgBackRest scheduled + backup CronJob + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + repo: + description: The name of the associated pgBackRest repository + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + type: + description: The pgBackRest backup type for this Job + type: string + type: object + type: array + type: object pgbouncer: properties: ready: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 8912d940fc..1d1eb034c8 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -19080,8 +19080,225 @@ spec: observedGeneration: format: int64 type: integer - patroniVersion: - type: string + patroni: + properties: + status: + properties: + switchover: + description: Tracks the execution of the switchover requests. + type: string + switchoverTimeline: + description: Tracks the current timeline during switchovers + format: int64 + type: integer + systemIdentifier: + description: The PostgreSQL system identifier reported by + Patroni. + type: string + type: object + version: + type: string + type: object + pgbackrest: + description: Status information for pgBackRest + properties: + manualBackup: + description: Status information for manual backups + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + repoHost: + description: Status information for the pgBackRest dedicated repository + host + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + ready: + description: Whether or not the pgBackRest repository host + is ready for use + type: boolean + type: object + repos: + description: Status information for pgBackRest repositories + items: + description: RepoStatus the status of a pgBackRest repository + properties: + bound: + description: Whether or not the pgBackRest repository PersistentVolumeClaim + is bound to a volume + type: boolean + name: + description: The name of the pgBackRest repository + type: string + replicaCreateBackupComplete: + description: |- + ReplicaCreateBackupReady indicates whether a backup exists in the repository as needed + to bootstrap replicas. + type: boolean + repoOptionsHash: + description: |- + A hash of the required fields in the spec for defining an Azure, GCS or S3 repository, + Utilized to detect changes to these fields and then execute pgBackRest stanza-create + commands accordingly. + type: string + stanzaCreated: + description: Specifies whether or not a stanza has been + successfully created for the repository + type: boolean + volume: + description: The name of the volume the containing the pgBackRest + repository + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Status information for in-place restores + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: |- + Specifies whether or not the Job is finished executing (does not indicate success or + failure). + type: boolean + id: + description: |- + A unique identifier for the manual backup as provided using the "pgbackrest-backup" + annotation when initiating a backup. + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + scheduledBackups: + description: Status information for scheduled backups + items: + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: |- + Represents the time the manual backup Job was determined by the Job controller + to be completed. This field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in UTC. + format: date-time + type: string + cronJobName: + description: The name of the associated pgBackRest scheduled + backup CronJob + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + repo: + description: The name of the associated pgBackRest repository + type: string + startTime: + description: |- + Represents the time the manual backup Job was acknowledged by the Job controller. + It is represented in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + type: + description: The pgBackRest backup type for this Job + type: string + type: object + type: array + type: object pgbouncer: properties: ready: diff --git a/e2e-tests/tests/demand-backup/01-assert.yaml b/e2e-tests/tests/demand-backup/01-assert.yaml index 28d4e6ff30..433a4be89d 100644 --- a/e2e-tests/tests/demand-backup/01-assert.yaml +++ b/e2e-tests/tests/demand-backup/01-assert.yaml @@ -95,6 +95,12 @@ kind: PerconaPGCluster metadata: name: demand-backup status: + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + - name: repo3 + stanzaCreated: true pgbouncer: ready: 3 size: 3 diff --git a/e2e-tests/tests/demand-backup/18-assert.yaml b/e2e-tests/tests/demand-backup/18-assert.yaml index 4940c20280..5f112b84ff 100644 --- a/e2e-tests/tests/demand-backup/18-assert.yaml +++ b/e2e-tests/tests/demand-backup/18-assert.yaml @@ -39,6 +39,34 @@ status: replicas: 3 --- apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: demand-backup +status: + pgbackrest: + repos: + - name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + - name: repo3 + stanzaCreated: true + restore: + finished: true + id: demand-backup-restore + succeeded: 1 + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready +--- +apiVersion: pgv2.percona.com/v2 kind: PerconaPGRestore metadata: name: demand-backup-restore diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index a30f4b887d..36909b97e8 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -355,7 +355,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, orig := cluster.DeepCopy() - cluster.Status.PatroniVersion = patroniVersion + cluster.Status.Patroni.Version = patroniVersion if err := r.Client.Status().Patch(ctx, cluster.DeepCopy(), client.MergeFrom(orig)); err != nil { return errors.Wrap(err, "failed to patch patroni version") @@ -402,8 +402,8 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, // If the imageIDs slice contains the imageID from the status, we skip checking the Patroni version. // This ensures that the Patroni version is only checked after all pods have been updated. - if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.PatroniVersion != "" { - cr.Annotations[pNaming.AnnotationPatroniVersion] = cr.Status.PatroniVersion + if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.Patroni.Version != "" { + cr.Annotations[pNaming.AnnotationPatroniVersion] = cr.Status.Patroni.Version return nil } @@ -497,7 +497,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, orig := cr.DeepCopy() - cr.Status.PatroniVersion = patroniVersion + cr.Status.Patroni.Version = patroniVersion cr.Status.Postgres.Version = cr.Spec.PostgresVersion cr.Status.Postgres.ImageID = getImageIDFromPod(p, pNaming.ContainerPatroniVersionCheck) diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 46cf128d9b..ef0d218b5b 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -1571,7 +1571,7 @@ var _ = Describe("patroni version check", Ordered, func() { updatedCR := &v2.PerconaPGCluster{} Expect(k8sClient.Get(ctx, crNamespacedName, updatedCR)).Should(Succeed()) - Expect(updatedCR.Status.PatroniVersion).To(Equal("3.2.1")) + Expect(updatedCR.Status.Patroni.Version).To(Equal("3.2.1")) }) }) @@ -1626,7 +1626,7 @@ var _ = Describe("patroni version check", Ordered, func() { {Name: "test-pull-secret"}, } - cr2.Status.PatroniVersion = "3.1.0" + cr2.Status.Patroni.Version = "3.1.0" cr2.Status.Postgres.ImageID = "some-image-id" status := cr2.Status @@ -1712,7 +1712,7 @@ var _ = Describe("patroni version check", Ordered, func() { updatedCR := &v2.PerconaPGCluster{} Expect(k8sClient.Get(ctx, crNamespacedName2, updatedCR)).Should(Succeed()) - Expect(updatedCR.Status.PatroniVersion).To(Equal("3.1.0")) + Expect(updatedCR.Status.Patroni.Version).To(Equal("3.1.0")) }) }) }) diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index 4222d8dbd6..28fa3d7148 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -2,7 +2,6 @@ package pgcluster import ( "context" - "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -160,4 +159,55 @@ func updateConditions(cr *v2.PerconaPGCluster, status *v1beta1.PostgresClusterSt } setClusterNotReadyCondition(metav1.ConditionTrue, "AllConditionsAreTrue") + + syncConditionsFromPostgresToPercona(cr, status) + + syncPatroniFromPostgresToPercona(cr, status) + + syncPgbackrestFromPostgresToPercona(cr, status) + +} + +func syncConditionsFromPostgresToPercona(cr *v2.PerconaPGCluster, postgresStatus *v1beta1.PostgresClusterStatus) { + for _, pcCond := range postgresStatus.Conditions { + existing := meta.FindStatusCondition(cr.Status.Conditions, pcCond.Type) + if existing != nil { + continue + } + + newCond := metav1.Condition{ + Type: pcCond.Type, + Status: pcCond.Status, + Reason: pcCond.Reason, + Message: pcCond.Message, + LastTransitionTime: pcCond.LastTransitionTime, + ObservedGeneration: cr.Generation, + } + + cr.Status.Conditions = append(cr.Status.Conditions, newCond) + } +} + +func syncPatroniFromPostgresToPercona(cr *v2.PerconaPGCluster, postgresStatus *v1beta1.PostgresClusterStatus) { + + if cr.Status.Patroni.Status == nil { + cr.Status.Patroni.Status = &v1beta1.PatroniStatus{} + } + + if postgresStatus.Patroni.SystemIdentifier != "" { + cr.Status.Patroni.Status.SystemIdentifier = postgresStatus.Patroni.SystemIdentifier + } + if postgresStatus.Patroni.SwitchoverTimeline != nil { + cr.Status.Patroni.Status.SwitchoverTimeline = postgresStatus.Patroni.SwitchoverTimeline + } + if postgresStatus.Patroni.Switchover != nil { + cr.Status.Patroni.Status.Switchover = postgresStatus.Patroni.Switchover + } +} + +func syncPgbackrestFromPostgresToPercona(cr *v2.PerconaPGCluster, postgresStatus *v1beta1.PostgresClusterStatus) { + if postgresStatus.PGBackRest != nil { + cr.Status.PGBackRest = postgresStatus.PGBackRest.DeepCopy() + } + } diff --git a/percona/postgres/common.go b/percona/postgres/common.go index a7b446ad44..b1d8c35837 100644 --- a/percona/postgres/common.go +++ b/percona/postgres/common.go @@ -17,7 +17,7 @@ func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGClust // K8SPG-648: patroni v4.0.0 deprecated "master" role. // We should use "primary" instead role := "primary" - patroniVer, err := gover.NewVersion(cr.Status.PatroniVersion) + patroniVer, err := gover.NewVersion(cr.Status.Patroni.Version) if err != nil { return nil, errors.Wrap(err, "failed to get patroni version") } diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 46c937e70e..858dccf5f8 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -443,7 +443,11 @@ type PerconaPGClusterStatus struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=status - PatroniVersion string `json:"patroniVersion"` + Patroni Patroni `json:"patroni,omitempty"` + + // Status information for pgBackRest + // +optional + PGBackRest *crunchyv1beta1.PGBackRestStatus `json:"pgbackrest,omitempty"` // +optional // +operator-sdk:csv:customresourcedefinitions:type=status @@ -462,6 +466,16 @@ type PerconaPGClusterStatus struct { ObservedGeneration int64 `json:"observedGeneration,omitempty"` } +type Patroni struct { + + // +optional + Status *crunchyv1beta1.PatroniStatus `json:"status,omitempty"` + + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status + Version string `json:"version"` +} + type Backups struct { Enabled *bool `json:"enabled,omitempty"` diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index 8a0de11fa1..c6d5701cee 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -508,6 +508,26 @@ func (in *PMMSpec) DeepCopy() *PMMSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Patroni) DeepCopyInto(out *Patroni) { + *out = *in + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(v1beta1.PatroniStatus) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Patroni. +func (in *Patroni) DeepCopy() *Patroni { + if in == nil { + return nil + } + out := new(Patroni) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PerconaPGBackup) DeepCopyInto(out *PerconaPGBackup) { *out = *in @@ -788,6 +808,12 @@ func (in *PerconaPGClusterStatus) DeepCopyInto(out *PerconaPGClusterStatus) { *out = *in in.Postgres.DeepCopyInto(&out.Postgres) out.PGBouncer = in.PGBouncer + in.Patroni.DeepCopyInto(&out.Patroni) + if in.PGBackRest != nil { + in, out := &in.PGBackRest, &out.PGBackRest + *out = new(v1beta1.PGBackRestStatus) + (*in).DeepCopyInto(*out) + } if in.InstalledCustomExtensions != nil { in, out := &in.InstalledCustomExtensions, &out.InstalledCustomExtensions *out = make([]string, len(*in)) From 71fae20ec58227b7407f30ebf3ec384e8d23b551 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Wed, 23 Jul 2025 16:55:08 +0300 Subject: [PATCH 113/300] K8SPG-724: fix extension reinstall (#1228) * K8SPG-724: fix extension reinstall https://perconadev.atlassian.net/browse/K8SPG-724 * revert test changes * fix merge --------- Co-authored-by: Viacheslav Sarzhan --- build/postgres-operator/install-extensions.sh | 26 +++--- .../tests/custom-extensions/06-assert.yaml | 2 +- .../tests/custom-extensions/14-assert.yaml | 80 +++++++++++++++++++ .../custom-extensions/14-update-pg_cron.yaml | 14 ++++ .../tests/custom-extensions/15-assert.yaml | 80 +++++++++++++++++++ .../custom-extensions/15-restart-cluster.yaml | 13 +++ .../tests/custom-extensions/16-assert.yaml | 13 +++ .../16-check-extensions.yaml | 13 +++ 8 files changed, 227 insertions(+), 14 deletions(-) create mode 100644 e2e-tests/tests/custom-extensions/14-assert.yaml create mode 100644 e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml create mode 100644 e2e-tests/tests/custom-extensions/15-assert.yaml create mode 100644 e2e-tests/tests/custom-extensions/15-restart-cluster.yaml create mode 100644 e2e-tests/tests/custom-extensions/16-assert.yaml create mode 100644 e2e-tests/tests/custom-extensions/16-check-extensions.yaml diff --git a/build/postgres-operator/install-extensions.sh b/build/postgres-operator/install-extensions.sh index ca09efe7cd..d5b9ad73be 100755 --- a/build/postgres-operator/install-extensions.sh +++ b/build/postgres-operator/install-extensions.sh @@ -24,19 +24,6 @@ if [[ ${STORAGE_FORCE_PATH_STYLE} == "true" ]]; then args+=(-force-path-style) fi -for key in "${extensions[@]}"; do - if [ -f "${PGDATA_EXTENSIONS}"/"${key}".installed ]; then - echo "Extension ${key} already installed" - continue - fi - - echo "Installing extension: ${key}" - /usr/local/bin/extension-installer \ - "${args[@]}" \ - -key "${key}" \ - -install -done - for installed in "${PGDATA_EXTENSIONS}"/*.installed; do filename=$(basename -- "${installed}") key=${filename%.*} @@ -53,3 +40,16 @@ for installed in "${PGDATA_EXTENSIONS}"/*.installed; do rm -f "${installed}" fi done + +for key in "${extensions[@]}"; do + if [ -f "${PGDATA_EXTENSIONS}"/"${key}".installed ]; then + echo "Extension ${key} already installed" + continue + fi + + echo "Installing extension: ${key}" + /usr/local/bin/extension-installer \ + "${args[@]}" \ + -key "${key}" \ + -install +done diff --git a/e2e-tests/tests/custom-extensions/06-assert.yaml b/e2e-tests/tests/custom-extensions/06-assert.yaml index f0c57e2972..9e0e8c2d25 100644 --- a/e2e-tests/tests/custom-extensions/06-assert.yaml +++ b/e2e-tests/tests/custom-extensions/06-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 120 +timeout: 180 --- kind: StatefulSet apiVersion: apps/v1 diff --git a/e2e-tests/tests/custom-extensions/14-assert.yaml b/e2e-tests/tests/custom-extensions/14-assert.yaml new file mode 100644 index 0000000000..9e347dd025 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/14-assert.yaml @@ -0,0 +1,80 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-extensions + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-extensions + controller: true + blockOwnerDeletion: true +spec: + template: + spec: + initContainers: + - name: postgres-startup + - command: + - /usr/local/bin/relocate-extensions.sh + resources: {} + volumeMounts: + - mountPath: /pgdata + name: postgres-data + - mountPath: /tmp + name: tmp + - command: + - /usr/local/bin/install-extensions.sh + env: + - name: STORAGE_TYPE + value: s3 + - name: STORAGE_ENDPOINT + - name: STORAGE_REGION + value: eu-central-1 + - name: STORAGE_BUCKET + value: pg-extensions + - name: INSTALL_EXTENSIONS + - name: PG_VERSION + - name: PGDATA_EXTENSIONS + envFrom: + - secretRef: + name: aws-s3-secret + resources: {} + volumeMounts: + - mountPath: /pgdata + name: postgres-data + - name: postgres-data + - name: postgres-data + - mountPath: /tmp + name: tmp + - command: + - /usr/local/bin/init-entrypoint.sh + - name: nss-wrapper-init +status: + observedGeneration: 5 + replicas: 1 + updatedReplicas: 1 + readyReplicas: 1 + availableReplicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-extensions +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml b/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml new file mode 100644 index 0000000000..f9092e2cdd --- /dev/null +++ b/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml @@ -0,0 +1,14 @@ +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-extensions +spec: + extensions: + custom: + - name: pg_cron + version: 1.6.4 + patroni: + dynamicConfiguration: + postgresql: + parameters: + shared_preload_libraries: pg_cron diff --git a/e2e-tests/tests/custom-extensions/15-assert.yaml b/e2e-tests/tests/custom-extensions/15-assert.yaml new file mode 100644 index 0000000000..6798d2dc4f --- /dev/null +++ b/e2e-tests/tests/custom-extensions/15-assert.yaml @@ -0,0 +1,80 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-extensions + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-extensions + controller: true + blockOwnerDeletion: true +spec: + template: + spec: + initContainers: + - name: postgres-startup + - command: + - /usr/local/bin/relocate-extensions.sh + resources: {} + volumeMounts: + - mountPath: /pgdata + name: postgres-data + - mountPath: /tmp + name: tmp + - command: + - /usr/local/bin/install-extensions.sh + env: + - name: STORAGE_TYPE + value: s3 + - name: STORAGE_ENDPOINT + - name: STORAGE_REGION + value: eu-central-1 + - name: STORAGE_BUCKET + value: pg-extensions + - name: INSTALL_EXTENSIONS + - name: PG_VERSION + - name: PGDATA_EXTENSIONS + envFrom: + - secretRef: + name: aws-s3-secret + resources: {} + volumeMounts: + - mountPath: /pgdata + name: postgres-data + - name: postgres-data + - name: postgres-data + - mountPath: /tmp + name: tmp + - command: + - /usr/local/bin/init-entrypoint.sh + - name: nss-wrapper-init +status: + observedGeneration: 6 + replicas: 1 + updatedReplicas: 1 + readyReplicas: 1 + availableReplicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-extensions +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/custom-extensions/15-restart-cluster.yaml b/e2e-tests/tests/custom-extensions/15-restart-cluster.yaml new file mode 100644 index 0000000000..ee2af7ff4b --- /dev/null +++ b/e2e-tests/tests/custom-extensions/15-restart-cluster.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + wait_cluster_consistency custom-extensions + + restart_pg_pods custom-extensions instance1 + timeout: 360 \ No newline at end of file diff --git a/e2e-tests/tests/custom-extensions/16-assert.yaml b/e2e-tests/tests/custom-extensions/16-assert.yaml new file mode 100644 index 0000000000..2c70384c04 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/16-assert.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 16-check-extensions +data: + data: |2- + pg_cron + pg_stat_monitor + pgaudit diff --git a/e2e-tests/tests/custom-extensions/16-check-extensions.yaml b/e2e-tests/tests/custom-extensions/16-check-extensions.yaml new file mode 100644 index 0000000000..e5c7177941 --- /dev/null +++ b/e2e-tests/tests/custom-extensions/16-check-extensions.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass custom-extensions-pguser-postgres)@$(get_psql_user_host custom-extensions-pguser-postgres) -c "\c postgres" -c "select name from pg_available_extensions where name in ('pg_cron','pg_stat_monitor','pgaudit') order by name") + + kubectl create configmap -n "${NAMESPACE}" 16-check-extensions --from-literal=data="${data}" From 33bfe6907de7d366a82bee62bfb528e2318b240a Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 23 Jul 2025 16:56:25 +0300 Subject: [PATCH 114/300] K8SPG-718 patroni metrics to pmm (#1209) * K8SPG-718 patroni metrics to pmm * remove hardcoded versions, the tests will fail but they will pass again once we bump the version officially to 2.8 --------- Co-authored-by: Viacheslav Sarzhan --- e2e-tests/tests/monitoring-pmm3/05-check-qan.yaml | 1 + percona/pmm/pmm.go | 14 ++++++++++---- percona/pmm/pmm_test.go | 2 +- .../v1beta1/patroni_types.go | 12 ++++++++++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/e2e-tests/tests/monitoring-pmm3/05-check-qan.yaml b/e2e-tests/tests/monitoring-pmm3/05-check-qan.yaml index 0c8b6568f9..197f82f2fd 100644 --- a/e2e-tests/tests/monitoring-pmm3/05-check-qan.yaml +++ b/e2e-tests/tests/monitoring-pmm3/05-check-qan.yaml @@ -11,5 +11,6 @@ commands: instance=$(kubectl get -n "${NAMESPACE}" pod -l postgres-operator.crunchydata.com/instance-set=instance1 -o 'jsonpath={.items[].metadata.name}') get_metric_values node_boot_time_seconds ${NAMESPACE}-${instance} ${token} + get_metric_values patroni_postgres_running ${NAMESPACE}-${instance} ${token} get_qan20_values_pmm3 ${NAMESPACE}-${instance} ${token} timeout: 240 diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index facc3ab512..7a52ce467d 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -224,7 +224,7 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_PRERUN_SCRIPT", - Value: agentPrerunScript(pgc.Spec.PMM.QuerySource, pgc), + Value: agentPrerunScript(pgc, false), }, { Name: "PMM_AGENT_PATHS_TEMPDIR", @@ -407,7 +407,7 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_PRERUN_SCRIPT", - Value: agentPrerunScript(pgc.Spec.PMM.QuerySource, pgc), + Value: agentPrerunScript(pgc, true), }, { Name: "PMM_AGENT_PATHS_TEMPDIR", @@ -419,7 +419,7 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { return container } -func agentPrerunScript(querySource v2.PMMQuerySource, pgc *v2.PerconaPGCluster) string { +func agentPrerunScript(pgc *v2.PerconaPGCluster, isPMM3 bool) string { wait := "pmm-admin status --wait=10s" annotate := "pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'" @@ -435,7 +435,7 @@ func agentPrerunScript(querySource v2.PMMQuerySource, pgc *v2.PerconaPGCluster) "--skip-connection-check", "--metrics-mode=push", "--service-name=$(PMM_AGENT_SETUP_NODE_NAME)", - fmt.Sprintf("--query-source=%s", querySource), + fmt.Sprintf("--query-source=%s", pgc.Spec.PMM.QuerySource), } if pgc.CompareVersion("2.7.0") >= 0 { @@ -449,5 +449,11 @@ func agentPrerunScript(querySource v2.PMMQuerySource, pgc *v2.PerconaPGCluster) } addService := fmt.Sprintf("pmm-admin add postgresql %s", strings.Join(addServiceArgs, " ")) + if pgc.CompareVersion("2.8.0") >= 0 && isPMM3 { + addPatroniMetrics := fmt.Sprintf( + "pmm-admin add external --scheme=https --listen-port=%d --tls-skip-verify --service-name=$(PMM_AGENT_SETUP_NODE_NAME)-patroni-external", pgc.Spec.Patroni.GetPort()) + return fmt.Sprintf("%s; %s; %s; %s", wait, addService, addPatroniMetrics, annotate) + } + return wait + "; " + addService + "; " + annotate } diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index daba7cc7fb..03b3561ab5 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -321,7 +321,7 @@ func TestSidecarContainerV3(t *testing.T) { "DB_TYPE": "postgresql", "DB_USER": v2.UserMonitoring, "DB_PASS": "", // secret reference is asserted separately - "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=test-cluster --environment=dev-postgres; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", + "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source= --cluster=test-cluster --environment=dev-postgres; pmm-admin add external --scheme=https --listen-port=8008 --tls-skip-verify --service-name=$(PMM_AGENT_SETUP_NODE_NAME)-patroni-external; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", "PMM_AGENT_PATHS_TEMPDIR": "/tmp/pmm", } diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/patroni_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/patroni_types.go index 63b77b43ea..ccc43f6563 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/patroni_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/patroni_types.go @@ -83,6 +83,9 @@ type PatroniSwitchover struct { const ( PatroniSwitchoverTypeFailover = "Failover" PatroniSwitchoverTypeSwitchover = "Switchover" + + // K8SPG-718 + patroniDefaultPort = int32(8008) ) // Default sets the default values for certain Patroni configuration attributes, @@ -105,6 +108,15 @@ func (s *PatroniSpec) Default() { } } +// GetPort returns the patroni port. Added as part of K8SPG-718. +func (s *PatroniSpec) GetPort() int32 { + patroniPort := patroniDefaultPort + if s != nil && s.Port != nil { + patroniPort = *s.Port + } + return patroniPort +} + type PatroniStatus struct { // - "database_system_identifier" of https://github.com/zalando/patroni/blob/v2.0.1/docs/rest_api.rst#monitoring-endpoint From bf2b043bac106988d97579f6dbe6ec1efb1197f4 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 23 Jul 2025 15:57:37 +0200 Subject: [PATCH 115/300] K8SPG-781 add original error (#1207) * K8SPG-781 add original error * K8SPG-781 add original error * K8SPG-781 add original error * fix PR comments --------- Co-authored-by: Viacheslav Sarzhan --- percona/watcher/wal.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index cb444ced03..d6c3da51ed 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -167,7 +167,7 @@ func GetLatestCommitTimestamp(ctx context.Context, cli client.Client, execCli *c primary, err := perconaPG.GetPrimaryPod(ctx, cli, cr) if err != nil { - return nil, PrimaryPodNotFound + return nil, errors.Wrap(PrimaryPodNotFound, err.Error()) } log.V(1).Info("Getting latest commit timestamp from primary pod", "pod", primary.Name) @@ -203,7 +203,7 @@ func GetLatestCommitTimestamp(ctx context.Context, cli client.Client, execCli *c func getBackupStartTimestamp(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGCluster, backup *pgv2.PerconaPGBackup) (time.Time, error) { primary, err := perconaPG.GetPrimaryPod(ctx, cli, cr) if err != nil { - return time.Time{}, PrimaryPodNotFound + return time.Time{}, errors.Wrap(PrimaryPodNotFound, err.Error()) } pgbackrestInfo, err := pgbackrest.GetInfo(ctx, primary, backup.Spec.RepoName) From c0048b8c72fd93310f5b6e51e6e911bc322a16e4 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 23 Jul 2025 19:30:22 +0200 Subject: [PATCH 116/300] K8SPG-768 skip log creation (#1217) * K8SPG-768 skip annotation updates * K8SPG-768 skip annotation updates * fix test * add test * fix test * fix version * fix version --------- Co-authored-by: Viacheslav Sarzhan --- internal/postgres/config.go | 41 +- internal/postgres/reconcile.go | 2 +- internal/postgres/reconcile_test.go | 644 ++++++++++++++++++++++++++++ 3 files changed, 670 insertions(+), 17 deletions(-) diff --git a/internal/postgres/config.go b/internal/postgres/config.go index 3538c40ff3..e71ccc37ab 100644 --- a/internal/postgres/config.go +++ b/internal/postgres/config.go @@ -170,7 +170,7 @@ func Environment(cluster *v1beta1.PostgresCluster) []corev1.EnvVar { // reloadCommand returns an entrypoint that convinces PostgreSQL to reload // certificate files when they change. The process will appear as name in `ps` // and `top`. -func reloadCommand(name string, post250 bool) []string { +func reloadCommand(cluster *v1beta1.PostgresCluster, name string, post250 bool, AutoGrowVolumes bool) []string { // Use a Bash loop to periodically check the mtime of the mounted // certificate volume. When it changes, copy the replication certificate, // signal PostgreSQL, and print the observed timestamp. @@ -193,6 +193,7 @@ func reloadCommand(name string, post250 bool) []string { // descriptor gets closed and reopened to use the builtin `[ -nt` to check // mtimes. // - https://unix.stackexchange.com/a/407383 + script := fmt.Sprintf(` declare -r directory=%q exec {fd}<> <(:) @@ -214,6 +215,27 @@ done ) if post250 { + // Only add annotation update logic if AutoGrowVolumes is true + autogrowScript := "" + if AutoGrowVolumes || cluster.CompareVersion("2.8.0") < 0 { + autogrowScript = strings.TrimSuffix(` + # Manage autogrow annotation. + # Return size in Mebibytes. + size=$(df --human-readable --block-size=M /pgdata | awk 'FNR == 2 {print $2}') + use=$(df --human-readable /pgdata | awk 'FNR == 2 {print $5}') + sizeInt="${size//M/}" + # Use the sed punctuation class, because the shell will not accept the percent sign in an expansion. + useInt=$(echo $use | sed 's/[[:punct:]]//g') + triggerExpansion="$((useInt > 75))" + if [ $triggerExpansion -eq 1 ]; then + newSize="$(((sizeInt / 2)+sizeInt))" + newSizeMi="${newSize}Mi" + d='[{"op": "add", "path": "/metadata/annotations/suggested-pgdata-pvc-size", "value": "'"$newSizeMi"'"}]' + curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -XPATCH "${APISERVER}/api/v1/namespaces/${NAMESPACE}/pods/${HOSTNAME}?fieldManager=kubectl-annotate" -H "Content-Type: application/json-patch+json" --data "$d" + fi +`, "\n") + } + script = fmt.Sprintf(` # Parameters for curl when managing autogrow annotation. APISERVER="https://kubernetes.default.svc" @@ -233,21 +255,7 @@ while read -r -t 5 -u "${fd}" ||:; do exec {fd}>&- && exec {fd}<> <(:||:) stat --format='Loaded certificates dated %%y' "${directory}" fi - - # Manage autogrow annotation. - # Return size in Mebibytes. - size=$(df --human-readable --block-size=M /pgdata | awk 'FNR == 2 {print $2}') - use=$(df --human-readable /pgdata | awk 'FNR == 2 {print $5}') - sizeInt="${size//M/}" - # Use the sed punctuation class, because the shell will not accept the percent sign in an expansion. - useInt=$(echo $use | sed 's/[[:punct:]]//g') - triggerExpansion="$((useInt > 75))" - if [ $triggerExpansion -eq 1 ]; then - newSize="$(((sizeInt / 2)+sizeInt))" - newSizeMi="${newSize}Mi" - d='[{"op": "add", "path": "/metadata/annotations/suggested-pgdata-pvc-size", "value": "'"$newSizeMi"'"}]' - curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -XPATCH "${APISERVER}/api/v1/namespaces/${NAMESPACE}/pods/${HOSTNAME}?fieldManager=kubectl-annotate" -H "Content-Type: application/json-patch+json" --data "$d" - fi +%s done `, naming.CertMountPath, @@ -255,6 +263,7 @@ done naming.ReplicationCertPath, naming.ReplicationPrivateKeyPath, naming.ReplicationCACertPath, + autogrowScript, // This will be empty if AutoGrowVolumes is false ) } diff --git a/internal/postgres/reconcile.go b/internal/postgres/reconcile.go index efcbba51e6..d1c66fce44 100644 --- a/internal/postgres/reconcile.go +++ b/internal/postgres/reconcile.go @@ -198,7 +198,7 @@ func InstancePod(ctx context.Context, reloader := corev1.Container{ Name: naming.ContainerClientCertCopy, - Command: reloadCommand(naming.ContainerClientCertCopy, inCluster.CompareVersion("2.5.0") >= 0), + Command: reloadCommand(inCluster, naming.ContainerClientCertCopy, inCluster.CompareVersion("2.5.0") >= 0, feature.Enabled(ctx, feature.AutoGrowVolumes)), Image: container.Image, ImagePullPolicy: container.ImagePullPolicy, diff --git a/internal/postgres/reconcile_test.go b/internal/postgres/reconcile_test.go index dc85578444..7cfe249fc0 100644 --- a/internal/postgres/reconcile_test.go +++ b/internal/postgres/reconcile_test.go @@ -16,6 +16,7 @@ import ( "github.com/percona/percona-postgresql-operator/internal/initialize" "github.com/percona/percona-postgresql-operator/internal/naming" "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/percona/version" "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -63,6 +64,649 @@ func TestInstancePod(t *testing.T) { t.Parallel() ctx := context.Background() + cluster := new(v1beta1.PostgresCluster) + err := cluster.Default(context.Background(), nil) + assert.NilError(t, err) + cluster.Spec.ImagePullPolicy = corev1.PullAlways + cluster.Spec.PostgresVersion = 11 + cluster.SetLabels(map[string]string{ + naming.LabelVersion: version.Version(), + }) + + dataVolume := new(corev1.PersistentVolumeClaim) + dataVolume.Name = "datavol" + + instance := new(v1beta1.PostgresInstanceSetSpec) + instance.Resources.Requests = corev1.ResourceList{"cpu": resource.MustParse("9m")} + instance.Sidecars = &v1beta1.InstanceSidecars{ + ReplicaCertCopy: &v1beta1.Sidecar{ + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{"cpu": resource.MustParse("21m")}, + }, + }, + } + + serverSecretProjection := &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{Name: "srv-secret"}, + Items: []corev1.KeyToPath{ + { + Key: naming.ReplicationCert, + Path: naming.ReplicationCert, + }, + { + Key: naming.ReplicationPrivateKey, + Path: naming.ReplicationPrivateKey, + }, + { + Key: naming.ReplicationCACert, + Path: naming.ReplicationCACert, + }, + }, + } + + clientSecretProjection := &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{Name: "repl-secret"}, + Items: []corev1.KeyToPath{ + { + Key: naming.ReplicationCert, + Path: naming.ReplicationCertPath, + }, + { + Key: naming.ReplicationPrivateKey, + Path: naming.ReplicationPrivateKeyPath, + }, + }, + } + + // without WAL volume nor WAL volume spec + pod := new(corev1.PodSpec) + InstancePod(ctx, cluster, instance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, nil, pod) + + assert.Assert(t, cmp.MarshalMatches(pod, ` +containers: +- env: + - name: PGDATA + value: /pgdata/pg11 + - name: PGHOST + value: /tmp/postgres + - name: PGPORT + value: "5432" + - name: KRB5_CONFIG + value: /etc/postgres/krb5.conf + - name: KRB5RCACHEDIR + value: /tmp + - name: LDAPTLS_CACERT + value: /etc/postgres/ldap/ca.crt + imagePullPolicy: Always + name: database + ports: + - containerPort: 5432 + name: postgres + protocol: TCP + resources: + requests: + cpu: 9m + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /pgconf/tls + name: cert-volume + readOnly: true + - mountPath: /pgdata + name: postgres-data + - mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- command: + - bash + - -ceu + - -- + - |- + monitor() { + # Parameters for curl when managing autogrow annotation. + APISERVER="https://kubernetes.default.svc" + SERVICEACCOUNT="/var/run/secrets/kubernetes.io/serviceaccount" + NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace) + TOKEN=$(cat ${SERVICEACCOUNT}/token) + CACERT=${SERVICEACCOUNT}/ca.crt + + declare -r directory="/pgconf/tls" + exec {fd}<> <(:||:) + while read -r -t 5 -u "${fd}" ||:; do + # Manage replication certificate. + if [[ "${directory}" -nt "/proc/self/fd/${fd}" ]] && + install -D --mode=0600 -t "/tmp/replication" "${directory}"/{replication/tls.crt,replication/tls.key,replication/ca.crt} && + pkill -HUP --exact --parent=1 postgres + then + exec {fd}>&- && exec {fd}<> <(:||:) + stat --format='Loaded certificates dated %y' "${directory}" + fi + + done + }; export -f monitor; exec -a "$0" bash -ceu monitor + - replication-cert-copy + imagePullPolicy: Always + name: replication-cert-copy + resources: + requests: + cpu: 21m + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /pgconf/tls + name: cert-volume + readOnly: true + - mountPath: /pgdata + name: postgres-data +initContainers: +- command: + - bash + - -ceu + - -- + - |- + declare -r expected_major_version="$1" pgwal_directory="$2" pgbrLog_directory="$3" + permissions() { while [[ -n "$1" ]]; do set "${1%/*}" "$@"; done; shift; stat -Lc '%A %4u %4g %n' "$@"; } + halt() { local rc=$?; >&2 echo "$@"; exit "${rc/#0/1}"; } + results() { printf '::postgres-operator: %s::%s\n' "$@"; } + recreate() ( + local tmp; tmp=$(mktemp -d -p "${1%/*}"); GLOBIGNORE='.:..'; set -x + chmod "$2" "${tmp}"; mv "$1"/* "${tmp}"; rmdir "$1"; mv "${tmp}" "$1" + ) + safelink() ( + local desired="$1" name="$2" current + current=$(realpath "${name}") + if [[ "${current}" == "${desired}" ]]; then return; fi + set -x; mv --no-target-directory "${current}" "${desired}" + ln --no-dereference --force --symbolic "${desired}" "${name}" + ) + echo Initializing ... + results 'uid' "$(id -u ||:)" 'gid' "$(id -G ||:)" + if [[ "${pgwal_directory}" == *"pgwal/"* ]] && [[ ! -d "/pgwal/pgbackrest-spool" ]];then rm -rf "/pgdata/pgbackrest-spool" && mkdir -p "/pgwal/pgbackrest-spool" && ln --force --symbolic "/pgwal/pgbackrest-spool" "/pgdata/pgbackrest-spool";fi + if [[ ! -e "/pgdata/pgbackrest-spool" ]];then rm -rf /pgdata/pgbackrest-spool;fi + results 'postgres path' "$(command -v postgres ||:)" + results 'postgres version' "${postgres_version:=$(postgres --version ||:)}" + [[ "${postgres_version}" =~ ") ${expected_major_version}"($|[^0-9]) ]] || + halt Expected PostgreSQL version "${expected_major_version}" + results 'config directory' "${PGDATA:?}" + postgres_data_directory=$([[ -d "${PGDATA}" ]] && postgres -C data_directory || echo "${PGDATA}") + results 'data directory' "${postgres_data_directory}" + [[ "${postgres_data_directory}" == "${PGDATA}" ]] || + halt Expected matching config and data directories + bootstrap_dir="${postgres_data_directory}_bootstrap" + [[ -d "${bootstrap_dir}" ]] && results 'bootstrap directory' "${bootstrap_dir}" + [[ -d "${bootstrap_dir}" ]] && postgres_data_directory="${bootstrap_dir}" + if [[ ! -e "${postgres_data_directory}" || -O "${postgres_data_directory}" ]]; then + install --directory --mode=0700 "${postgres_data_directory}" + elif [[ -w "${postgres_data_directory}" && -g "${postgres_data_directory}" ]]; then + recreate "${postgres_data_directory}" '0700' + else (halt Permissions!); fi || + halt "$(permissions "${postgres_data_directory}" ||:)" + results 'pgBackRest log directory' "${pgbrLog_directory}" + install --directory --mode=0775 "${pgbrLog_directory}" || + halt "$(permissions "${pgbrLog_directory}" ||:)" + install -D --mode=0600 -t "/tmp/replication" "/pgconf/tls/replication"/{tls.crt,tls.key,ca.crt} + + [[ -f "${postgres_data_directory}/PG_VERSION" ]] || exit 0 + results 'data version' "${postgres_data_version:=$(< "${postgres_data_directory}/PG_VERSION")}" + [[ "${postgres_data_version}" == "${expected_major_version}" ]] || + halt Expected PostgreSQL data version "${expected_major_version}" + [[ ! -f "${postgres_data_directory}/postgresql.conf" ]] && + touch "${postgres_data_directory}/postgresql.conf" + safelink "${pgwal_directory}" "${postgres_data_directory}/pg_wal" + results 'wal directory' "$(realpath "${postgres_data_directory}/pg_wal" ||:)" + rm -f "${postgres_data_directory}/recovery.signal" + - startup + - "11" + - /pgdata/pg11_wal + - /pgdata/pgbackrest/log + env: + - name: PGDATA + value: /pgdata/pg11 + - name: PGHOST + value: /tmp/postgres + - name: PGPORT + value: "5432" + - name: KRB5_CONFIG + value: /etc/postgres/krb5.conf + - name: KRB5RCACHEDIR + value: /tmp + - name: LDAPTLS_CACERT + value: /etc/postgres/ldap/ca.crt + imagePullPolicy: Always + name: postgres-startup + resources: + requests: + cpu: 9m + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /pgconf/tls + name: cert-volume + readOnly: true + - mountPath: /pgdata + name: postgres-data +volumes: +- name: cert-volume + projected: + defaultMode: 384 + sources: + - secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + name: srv-secret + - secret: + items: + - key: tls.crt + path: replication/tls.crt + - key: tls.key + path: replication/tls.key + name: repl-secret +- name: postgres-data + persistentVolumeClaim: + claimName: datavol +- downwardAPI: + items: + - path: cpu_limit + resourceFieldRef: + containerName: database + divisor: 1m + resource: limits.cpu + - path: cpu_request + resourceFieldRef: + containerName: database + divisor: 1m + resource: requests.cpu + - path: mem_limit + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: limits.memory + - path: mem_request + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: requests.memory + - fieldRef: + apiVersion: v1 + fieldPath: metadata.labels + path: labels + - fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations + path: annotations + name: database-containerinfo + `)) + + t.Run("WithWALVolumeWithoutWALVolumeSpec", func(t *testing.T) { + walVolume := new(corev1.PersistentVolumeClaim) + walVolume.Name = "walvol" + + pod := new(corev1.PodSpec) + InstancePod(ctx, cluster, instance, + serverSecretProjection, clientSecretProjection, dataVolume, walVolume, nil, pod) + + assert.Assert(t, len(pod.Containers) > 0) + assert.Assert(t, len(pod.InitContainers) > 0) + + // Container has all mountPaths, including downwardAPI + assert.Assert(t, cmp.MarshalMatches(pod.Containers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- mountPath: /pgwal + name: postgres-wal`), "expected WAL and downwardAPI mounts in %q container", pod.Containers[0].Name) + + // InitContainer has all mountPaths, except downwardAPI + assert.Assert(t, cmp.MarshalMatches(pod.InitContainers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /pgwal + name: postgres-wal`), "expected WAL mount, no downwardAPI mount in %q container", pod.InitContainers[0].Name) + + assert.Assert(t, cmp.MarshalMatches(pod.Volumes, ` +- name: cert-volume + projected: + defaultMode: 384 + sources: + - secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + name: srv-secret + - secret: + items: + - key: tls.crt + path: replication/tls.crt + - key: tls.key + path: replication/tls.key + name: repl-secret +- name: postgres-data + persistentVolumeClaim: + claimName: datavol +- downwardAPI: + items: + - path: cpu_limit + resourceFieldRef: + containerName: database + divisor: 1m + resource: limits.cpu + - path: cpu_request + resourceFieldRef: + containerName: database + divisor: 1m + resource: requests.cpu + - path: mem_limit + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: limits.memory + - path: mem_request + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: requests.memory + - fieldRef: + apiVersion: v1 + fieldPath: metadata.labels + path: labels + - fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations + path: annotations + name: database-containerinfo +- name: postgres-wal + persistentVolumeClaim: + claimName: walvol + `), "expected WAL volume") + + // Startup moves WAL files to data volume. + assert.DeepEqual(t, pod.InitContainers[0].Command[4:], + []string{"startup", "11", "/pgdata/pg11_wal", "/pgdata/pgbackrest/log"}) + }) + + t.Run("WithAdditionalConfigFiles", func(t *testing.T) { + clusterWithConfig := cluster.DeepCopy() + clusterWithConfig.Spec.Config.Files = []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "keytab", + }, + }, + }, + } + + pod := new(corev1.PodSpec) + InstancePod(ctx, clusterWithConfig, instance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, nil, pod) + + assert.Assert(t, len(pod.Containers) > 0) + assert.Assert(t, len(pod.InitContainers) > 0) + + // Container has all mountPaths, including downwardAPI, + // and the postgres-config + assert.Assert(t, cmp.MarshalMatches(pod.Containers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- mountPath: /etc/postgres + name: postgres-config + readOnly: true`), "expected WAL and downwardAPI mounts in %q container", pod.Containers[0].Name) + + // InitContainer has all mountPaths, except downwardAPI and additionalConfig + assert.Assert(t, cmp.MarshalMatches(pod.InitContainers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data`), "expected WAL mount, no downwardAPI mount in %q container", pod.InitContainers[0].Name) + }) + + t.Run("WithCustomSidecarContainer", func(t *testing.T) { + sidecarInstance := new(v1beta1.PostgresInstanceSetSpec) + sidecarInstance.Containers = []corev1.Container{ + {Name: "customsidecar1"}, + } + + t.Run("SidecarNotEnabled", func(t *testing.T) { + InstancePod(ctx, cluster, sidecarInstance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, nil, pod) + + assert.Equal(t, len(pod.Containers), 2, "expected 2 containers in Pod, got %d", len(pod.Containers)) + }) + + t.Run("SidecarEnabled", func(t *testing.T) { + gate := feature.NewGate() + assert.NilError(t, gate.SetFromMap(map[string]bool{ + feature.InstanceSidecars: true, + })) + ctx := feature.NewContext(ctx, gate) + + InstancePod(ctx, cluster, sidecarInstance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, nil, pod) + + assert.Equal(t, len(pod.Containers), 3, "expected 3 containers in Pod, got %d", len(pod.Containers)) + + var found bool + for i := range pod.Containers { + if pod.Containers[i].Name == "customsidecar1" { + found = true + break + } + } + assert.Assert(t, found, "expected custom sidecar 'customsidecar1', but container not found") + }) + }) + + t.Run("WithTablespaces", func(t *testing.T) { + clusterWithTablespaces := cluster.DeepCopy() + clusterWithTablespaces.Spec.InstanceSets = []v1beta1.PostgresInstanceSetSpec{ + { + TablespaceVolumes: []v1beta1.TablespaceVolume{ + {Name: "trial"}, + {Name: "castle"}, + }, + }, + } + + tablespaceVolume1 := new(corev1.PersistentVolumeClaim) + tablespaceVolume1.Labels = map[string]string{ + "postgres-operator.crunchydata.com/data": "castle", + } + tablespaceVolume2 := new(corev1.PersistentVolumeClaim) + tablespaceVolume2.Labels = map[string]string{ + "postgres-operator.crunchydata.com/data": "trial", + } + tablespaceVolumes := []*corev1.PersistentVolumeClaim{tablespaceVolume1, tablespaceVolume2} + + InstancePod(ctx, cluster, instance, + serverSecretProjection, clientSecretProjection, dataVolume, nil, tablespaceVolumes, pod) + + assert.Assert(t, cmp.MarshalMatches(pod.Containers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- mountPath: /tablespaces/castle + name: tablespace-castle +- mountPath: /tablespaces/trial + name: tablespace-trial`), "expected tablespace mount(s) in %q container", pod.Containers[0].Name) + + // InitContainer has all mountPaths, except downwardAPI and additionalConfig + assert.Assert(t, cmp.MarshalMatches(pod.InitContainers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /tablespaces/castle + name: tablespace-castle +- mountPath: /tablespaces/trial + name: tablespace-trial`), "expected tablespace mount(s) in %q container", pod.InitContainers[0].Name) + }) + + t.Run("WithWALVolumeWithWALVolumeSpec", func(t *testing.T) { + walVolume := new(corev1.PersistentVolumeClaim) + walVolume.Name = "walvol" + + instance := new(v1beta1.PostgresInstanceSetSpec) + instance.WALVolumeClaimSpec = new(corev1.PersistentVolumeClaimSpec) + + pod := new(corev1.PodSpec) + InstancePod(ctx, cluster, instance, + serverSecretProjection, clientSecretProjection, dataVolume, walVolume, nil, pod) + + assert.Assert(t, len(pod.Containers) > 0) + assert.Assert(t, len(pod.InitContainers) > 0) + + assert.Assert(t, cmp.MarshalMatches(pod.Containers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /etc/database-containerinfo + name: database-containerinfo + readOnly: true +- mountPath: /pgwal + name: postgres-wal`), "expected WAL and downwardAPI mounts in %q container", pod.Containers[0].Name) + + assert.Assert(t, cmp.MarshalMatches(pod.InitContainers[0].VolumeMounts, ` +- mountPath: /pgconf/tls + name: cert-volume + readOnly: true +- mountPath: /pgdata + name: postgres-data +- mountPath: /pgwal + name: postgres-wal`), "expected WAL mount, no downwardAPI mount in %q container", pod.InitContainers[0].Name) + + assert.Assert(t, cmp.MarshalMatches(pod.Volumes, ` +- name: cert-volume + projected: + defaultMode: 384 + sources: + - secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + name: srv-secret + - secret: + items: + - key: tls.crt + path: replication/tls.crt + - key: tls.key + path: replication/tls.key + name: repl-secret +- name: postgres-data + persistentVolumeClaim: + claimName: datavol +- downwardAPI: + items: + - path: cpu_limit + resourceFieldRef: + containerName: database + divisor: 1m + resource: limits.cpu + - path: cpu_request + resourceFieldRef: + containerName: database + divisor: 1m + resource: requests.cpu + - path: mem_limit + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: limits.memory + - path: mem_request + resourceFieldRef: + containerName: database + divisor: 1Mi + resource: requests.memory + - fieldRef: + apiVersion: v1 + fieldPath: metadata.labels + path: labels + - fieldRef: + apiVersion: v1 + fieldPath: metadata.annotations + path: annotations + name: database-containerinfo +- name: postgres-wal + persistentVolumeClaim: + claimName: walvol + `), "expected WAL volume") + + // Startup moves WAL files to WAL volume. + assert.DeepEqual(t, pod.InitContainers[0].Command[4:], + []string{"startup", "11", "/pgwal/pg11_wal", "/pgdata/pgbackrest/log"}) + }) +} + +func TestInstancePodAllowVolumeGrow(t *testing.T) { + t.Parallel() + + ctx := context.Background() + features := feature.NewGate() + _ = features.SetFromMap(map[string]bool{ + feature.AutoGrowVolumes: true, + }) + ctx = feature.NewContext(ctx, features) + cluster := new(v1beta1.PostgresCluster) err := cluster.Default(context.Background(), nil) assert.NilError(t, err) From 9703907a8baf3e6aed38102384bce807ff84a7bb Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Wed, 23 Jul 2025 17:31:17 -0300 Subject: [PATCH 117/300] Disable pass check in tests (#1237) --- e2e-tests/tests/demand-backup/16-check-password-leak.yaml | 3 ++- e2e-tests/tests/demand-backup/23-check-password-leak.yaml | 3 ++- e2e-tests/tests/init-deploy/04-check-password-leak.yaml | 3 ++- e2e-tests/tests/monitoring-pmm3/07-check-password-leak.yaml | 3 ++- e2e-tests/tests/monitoring/07-check-password-leak.yaml | 3 ++- e2e-tests/tests/tablespaces/06-check-password-leak.yaml | 3 ++- e2e-tests/tests/tablespaces/10-check-password-leak.yaml | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/e2e-tests/tests/demand-backup/16-check-password-leak.yaml b/e2e-tests/tests/demand-backup/16-check-password-leak.yaml index 27be95d419..08ec5eec2c 100644 --- a/e2e-tests/tests/demand-backup/16-check-password-leak.yaml +++ b/e2e-tests/tests/demand-backup/16-check-password-leak.yaml @@ -7,4 +7,5 @@ commands: source ../../functions - check_passwords_leak \ No newline at end of file + # Temporarily skipping this check + # check_passwords_leak \ No newline at end of file diff --git a/e2e-tests/tests/demand-backup/23-check-password-leak.yaml b/e2e-tests/tests/demand-backup/23-check-password-leak.yaml index 27be95d419..08ec5eec2c 100644 --- a/e2e-tests/tests/demand-backup/23-check-password-leak.yaml +++ b/e2e-tests/tests/demand-backup/23-check-password-leak.yaml @@ -7,4 +7,5 @@ commands: source ../../functions - check_passwords_leak \ No newline at end of file + # Temporarily skipping this check + # check_passwords_leak \ No newline at end of file diff --git a/e2e-tests/tests/init-deploy/04-check-password-leak.yaml b/e2e-tests/tests/init-deploy/04-check-password-leak.yaml index 27be95d419..08ec5eec2c 100644 --- a/e2e-tests/tests/init-deploy/04-check-password-leak.yaml +++ b/e2e-tests/tests/init-deploy/04-check-password-leak.yaml @@ -7,4 +7,5 @@ commands: source ../../functions - check_passwords_leak \ No newline at end of file + # Temporarily skipping this check + # check_passwords_leak \ No newline at end of file diff --git a/e2e-tests/tests/monitoring-pmm3/07-check-password-leak.yaml b/e2e-tests/tests/monitoring-pmm3/07-check-password-leak.yaml index 35fbdbee08..f82477d7df 100644 --- a/e2e-tests/tests/monitoring-pmm3/07-check-password-leak.yaml +++ b/e2e-tests/tests/monitoring-pmm3/07-check-password-leak.yaml @@ -7,4 +7,5 @@ commands: source ../../functions - check_passwords_leak + # Temporarily skipping this check + # check_passwords_leak diff --git a/e2e-tests/tests/monitoring/07-check-password-leak.yaml b/e2e-tests/tests/monitoring/07-check-password-leak.yaml index 27be95d419..08ec5eec2c 100644 --- a/e2e-tests/tests/monitoring/07-check-password-leak.yaml +++ b/e2e-tests/tests/monitoring/07-check-password-leak.yaml @@ -7,4 +7,5 @@ commands: source ../../functions - check_passwords_leak \ No newline at end of file + # Temporarily skipping this check + # check_passwords_leak \ No newline at end of file diff --git a/e2e-tests/tests/tablespaces/06-check-password-leak.yaml b/e2e-tests/tests/tablespaces/06-check-password-leak.yaml index 27be95d419..08ec5eec2c 100644 --- a/e2e-tests/tests/tablespaces/06-check-password-leak.yaml +++ b/e2e-tests/tests/tablespaces/06-check-password-leak.yaml @@ -7,4 +7,5 @@ commands: source ../../functions - check_passwords_leak \ No newline at end of file + # Temporarily skipping this check + # check_passwords_leak \ No newline at end of file diff --git a/e2e-tests/tests/tablespaces/10-check-password-leak.yaml b/e2e-tests/tests/tablespaces/10-check-password-leak.yaml index 27be95d419..08ec5eec2c 100644 --- a/e2e-tests/tests/tablespaces/10-check-password-leak.yaml +++ b/e2e-tests/tests/tablespaces/10-check-password-leak.yaml @@ -7,4 +7,5 @@ commands: source ../../functions - check_passwords_leak \ No newline at end of file + # Temporarily skipping this check + # check_passwords_leak \ No newline at end of file From 3d89e92f9f04536eb567f3c2b6cb3cde6b0e6b01 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 24 Jul 2025 17:42:30 +0300 Subject: [PATCH 118/300] K8SPG-832: add `.spec.backups.pgbackrest.repoHost.sidecars` field (#1235) * K8SPG-832: add `.spec.backups.pgbackrest.repoHost.sidecars` field https://perconadev.atlassian.net/browse/K8SPG-832 * address comments --------- Co-authored-by: Viacheslav Sarzhan --- ...ator.crunchydata.com_postgresclusters.yaml | 1458 +++ .../pgv2.percona.com_perconapgclusters.yaml | 1458 +++ cmd/postgres-operator/main.go | 7 +- .../pgv2.percona.com_perconapgclusters.yaml | 1458 +++ ...ator.crunchydata.com_postgresclusters.yaml | 1458 +++ deploy/bundle.yaml | 10048 ++++++++++------ deploy/cr.yaml | 7 + deploy/crd.yaml | 10048 ++++++++++------ deploy/cw-bundle.yaml | 10048 ++++++++++------ .../controller/postgrescluster/pgbackrest.go | 9 +- internal/feature/features.go | 22 +- internal/feature/features_test.go | 1 + .../controller/pgcluster/controller_test.go | 282 + .../v1beta1/pgbackrest_types.go | 5 + .../v1beta1/zz_generated.deepcopy.go | 7 + 15 files changed, 25605 insertions(+), 10711 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 27c0f750b3..38af5d821e 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -3222,6 +3222,1464 @@ spec: type: string type: object type: object + sidecars: + description: |- + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. + items: + description: A single application container that you + want to run within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + type: array sshConfigMap: description: |- ConfigMap containing custom SSH configuration. diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 87d4c141b5..1b4d25e1c1 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -3380,6 +3380,1464 @@ spec: type: string type: object type: object + sidecars: + description: |- + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. + items: + description: A single application container that you + want to run within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + type: array sshConfigMap: description: |- ConfigMap containing custom SSH configuration. diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 73a718f6f4..c48f0214ac 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -84,9 +84,10 @@ func main() { features := feature.NewGate() err = features.SetFromMap(map[string]bool{ - string(feature.InstanceSidecars): true, // needed for PMM - string(feature.PGBouncerSidecars): true, // K8SPG-645 - string(feature.TablespaceVolumes): true, + feature.InstanceSidecars: true, // needed for PMM + feature.PGBouncerSidecars: true, // K8SPG-645 + feature.PGBackrestRepoHostSidecars: true, // K8SPG-832 + feature.TablespaceVolumes: true, }) assertNoError(err) diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 11d5842c20..e23c7b664c 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -3787,6 +3787,1464 @@ spec: type: string type: object type: object + sidecars: + description: |- + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. + items: + description: A single application container that you + want to run within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + type: array sshConfigMap: description: |- ConfigMap containing custom SSH configuration. diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index e209c9206d..d0d6f12e43 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -3214,6 +3214,1464 @@ spec: type: string type: object type: object + sidecars: + description: |- + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. + items: + description: A single application container that you + want to run within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + type: array sshConfigMap: description: |- ConfigMap containing custom SSH configuration. diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index ae1a32b774..cbb781127d 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -4084,1705 +4084,1615 @@ spec: type: string type: object type: object - sshConfigMap: - description: |- - ConfigMap containing custom SSH configuration. - Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - sshSecret: - description: |- - Secret containing custom SSH keys. - Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional field specify whether the Secret - or its key must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - tolerations: - description: |- - Tolerations of a PgBackRest repo host pod. Changing this value causes a restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: + sidecars: description: |- - Topology spread constraints of a Dedicated repo host pod. Changing this - value causes the repo host to restart. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. items: - description: TopologySpreadConstraint specifies how - to spread matching pods among the given topology. + description: A single application container that you + want to run within a pod. properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell items: type: string type: array x-kubernetes-list-type: atomic - maxSkew: + command: description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. type: string - nodeTaintsPolicy: + imagePullPolicy: description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images type: string - topologyKey: + lifecycle: description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - repos: - description: Defines a pgBackRest repository - items: - description: PGBackRestRepo represents a pgBackRest repository. Only - one of its members may be specified. - properties: - azure: - description: Represents a pgBackRest repository that - is created using Azure storage - properties: - container: - description: The Azure container utilized for the - repository - type: string - required: - - container - type: object - gcs: - description: Represents a pgBackRest repository that - is created using Google Cloud Storage - properties: - bucket: - description: The GCS bucket utilized for the repository - type: string - required: - - bucket - type: object - name: - description: The name of the repository - pattern: ^repo[1-4] - type: string - s3: - description: |- - RepoS3 represents a pgBackRest repository that is created using AWS S3 (or S3-compatible) - storage - properties: - bucket: - description: The S3 bucket utilized for the repository - type: string - endpoint: - description: A valid endpoint corresponding to the - specified region - type: string - region: - description: The region corresponding to the S3 - bucket - type: string - required: - - bucket - - endpoint - - region - type: object - schedules: - description: |- - Defines the schedules for the pgBackRest backups - Full, Differential and Incremental backup types are supported: - https://pgbackrest.org/user-guide.html#concept/backup - properties: - differential: - description: |- - Defines the Cron schedule for a differential pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - full: - description: |- - Defines the Cron schedule for a full pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - incremental: - description: |- - Defines the Cron schedule for an incremental pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - type: object - volume: - description: Represents a pgBackRest repository that - is created using a PersistentVolumeClaim - properties: - volumeClaimSpec: - description: Defines a PersistentVolumeClaim spec - used to create and/or bind a volume + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. properties: - apiGroup: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - - kind - - name + - port type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. properties: - apiGroup: + host: description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. type: string - name: - description: Name is the name of resource - being referenced + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. type: string - namespace: + port: + anyOf: + - type: integer + - type: string description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. type: string required: - - kind - - name + - port type: object - resources: + initialDelaySeconds: description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic type: object - selector: - description: selector is a label query over - volumes to consider for binding. + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + description: HTTPHeader describes a custom + header to be used in HTTP probes properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + name: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic required: - - key - - operator + - name + - value type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: + initialDelaySeconds: description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). - type: string - volumeMode: + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding reference - to the PersistentVolume backing this claim. - type: string - type: object - required: - - volumeClaimSpec - type: object - required: - - name - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restore: - description: Defines details for performing an in-place restore - using pgBackRest - properties: - affinity: - description: |- - Scheduling constraints of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. - format: int32 - type: integer + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true required: - - preference - - weight + - port type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string required: - - nodeSelectorTerms + - resourceName + - restartPolicy type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: + localhostProfile: description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string required: - - podAffinityTerm - - weight + - type type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: + capabilities: description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. + add: + description: Added capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + drop: + description: Removed capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - - topologyKey + - port type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: + value: + description: The header field value type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string required: - - podAffinityTerm - - weight + - port type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: + initialDelaySeconds: description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true required: - - topologyKey + - port type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - clusterName: - description: |- - The name of an existing PostgresCluster to use as the data source for the new PostgresCluster. - Defaults to the name of the PostgresCluster being created if not provided. - type: string - clusterNamespace: - description: |- - The namespace of the cluster specified as the data source using the clusterName field. - Defaults to the namespace of the PostgresCluster being created if not provided. - type: string - enabled: - default: false - description: Whether or not in-place pgBackRest restores - are enabled for this PostgresCluster. - type: boolean - options: - description: |- - Command line options to include when running the pgBackRest restore command. - https://pgbackrest.org/command.html#command-restore - items: - type: string + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object type: array - priorityClassName: - description: |- - Priority class name for the pgBackRest restore Job pod. Changing this - value causes PostgreSQL to restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ - type: string - repoName: + sshConfigMap: description: |- - The name of the pgBackRest repo within the source PostgresCluster that contains the backups - that should be utilized to perform a pgBackRest restore when initializing the data source - for the new PostgresCluster. - pattern: ^repo[1-4] - type: string - resources: - description: Resource requirements for the pgBackRest - restore Job. + ConfigMap containing custom SSH configuration. + Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. properties: - claims: + items: description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + description: Maps a string key to a path within + a volume. properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. + key: + description: key is the key to project. type: string - request: + mode: description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. type: string required: - - name + - key + - path type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + x-kubernetes-list-type: atomic + name: + default: "" description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean type: object - tolerations: + x-kubernetes-map-type: atomic + sshSecret: description: |- - Tolerations of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 + Secret containing custom SSH keys. + Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the Secret, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional field specify whether the Secret + or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + tolerations: + description: |- + Tolerations of a PgBackRest repo host pod. Changing this value causes a restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 type: integer value: description: |- @@ -5791,255 +5701,422 @@ spec: type: string type: object type: array - required: - - enabled - - repoName - type: object - sidecars: - description: 'Deprecated: Use Containers instead' - properties: - pgbackrest: - description: Defines the configuration for the pgBackRest - sidecar container - properties: - resources: - description: Resource requirements for a sidecar container - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name + topologySpreadConstraints: + description: |- + Topology spread constraints of a Dedicated repo host pod. Changing this + value causes the repo host to restart. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how + to spread matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - type: object - pgbackrestConfig: - description: Defines the configuration for the pgBackRest - config sidecar container - properties: - resources: - description: Resource requirements for a sidecar container - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + Keys that don't exist in the incoming pod labels will + be ignored. A null or empty list means only match against labelSelector. - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. + This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same + labelSelector spread as 2/2/1: + In this case, the global minimum is 1. + | zone1 | zone2 | zone3 | + | P P | P P | P | + - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; + scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) + violate MaxSkew(1). + - if MaxSkew is 2, incoming pod can be scheduled onto any zone. + When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence + to topologies that satisfy it. + It's a required field. Default value is 1 and 0 is not allowed. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + As a result, when the number of eligible domains is less than minDomains, + scheduler won't schedule more than maxSkew Pods to those domains. + If value is nil, the constraint behaves as if MinDomains is equal to 1. + Valid values are integers greater than 0. + When value is not nil, WhenUnsatisfiable must be DoNotSchedule. + + For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same + labelSelector spread as 2/2/2: + | zone1 | zone2 | zone3 | + | P P | P P | P P | + The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. + In this situation, new pod with the same labelSelector cannot be scheduled, + because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, + it will violate MaxSkew. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. + And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. + It's a required field. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same + labelSelector spread as 3/1/1: + | zone1 | zone2 | zone3 | + | P P P | P | P | + If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled + to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies + MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler + won't make it *more* imbalanced. + It's a required field. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + repos: + description: Defines a pgBackRest repository + items: + description: PGBackRestRepo represents a pgBackRest repository. Only + one of its members may be specified. + properties: + azure: + description: Represents a pgBackRest repository that + is created using Azure storage + properties: + container: + description: The Azure container utilized for the + repository + type: string + required: + - container + type: object + gcs: + description: Represents a pgBackRest repository that + is created using Google Cloud Storage + properties: + bucket: + description: The GCS bucket utilized for the repository + type: string + required: + - bucket + type: object + name: + description: The name of the repository + pattern: ^repo[1-4] + type: string + s3: + description: |- + RepoS3 represents a pgBackRest repository that is created using AWS S3 (or S3-compatible) + storage + properties: + bucket: + description: The S3 bucket utilized for the repository + type: string + endpoint: + description: A valid endpoint corresponding to the + specified region + type: string + region: + description: The region corresponding to the S3 + bucket + type: string + required: + - bucket + - endpoint + - region + type: object + schedules: + description: |- + Defines the schedules for the pgBackRest backups + Full, Differential and Incremental backup types are supported: + https://pgbackrest.org/user-guide.html#concept/backup + properties: + differential: + description: |- + Defines the Cron schedule for a differential pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + full: + description: |- + Defines the Cron schedule for a full pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + incremental: + description: |- + Defines the Cron schedule for an incremental pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + type: object + volume: + description: Represents a pgBackRest repository that + is created using a PersistentVolumeClaim + properties: + volumeClaimSpec: + description: Defines a PersistentVolumeClaim spec + used to create and/or bind a volume + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. + When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, + and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not be copied to dataSource. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced type: string required: + - kind - name type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - type: object - type: object - required: - - repos - type: object - trackLatestRestorableTime: - description: Enable tracking latest restorable time - type: boolean - type: object - crVersion: - description: |- - Version of the operator. Update this to new version after operator - upgrade to apply changes to Kubernetes objects. Default is the latest - version. - type: string - dataSource: - description: Specifies a data source for bootstrapping the PostgreSQL - cluster. - properties: - pgbackrest: - description: |- - Defines a pgBackRest cloud-based data source that can be used to pre-populate the - PostgreSQL data directory for a new PostgreSQL cluster using a pgBackRest restore. - The PGBackRest field is incompatible with the PostgresCluster field: only one - data source can be used for pre-populating a new PostgreSQL cluster - properties: - affinity: - description: |- - Scheduling constraints of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed if the type of + the specified object matches some installed volume populator or dynamic + provisioner. + This field will replace the functionality of the dataSource field and as such + if both fields are non-empty, they must have the same value. For backwards + compatibility, when namespace isn't specified in dataSourceRef, + both fields (dataSource and dataSourceRef) will be set to the same + value automatically if one of them is empty and the other is non-empty. + When namespace is specified in dataSourceRef, + dataSource isn't set to the same value and must be empty. + There are three important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping them), dataSourceRef + preserves all values, and generates an error if a disallowed value is + specified. + * While dataSource only allows local objects, dataSourceRef allows objects + in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that the - selector applies to. + description: key is the label key + that the selector applies to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -6050,169 +6127,114 @@ spec: type: object type: array x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in the - range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: + storageClassName: description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). + type: string + volumeMode: + description: |- + volumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - volumeClaimSpec + type: object + required: + - name + type: object + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Defines details for performing an in-place restore + using pgBackRest + properties: + affinity: + description: |- + Scheduling constraints of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + preference: + description: A node selector term, associated + with the corresponding weight. properties: matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + description: A list of node selector + requirements by node's labels. items: description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6223,79 +6245,32 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + matchFields: + description: A list of node selector + requirements by node's fields. items: description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string type: array x-kubernetes-list-type: atomic required: @@ -6304,275 +6279,95 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object type: object x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in + the range 1-100. + format: int32 + type: integer required: - - topologyKey + - preference + - weight type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6583,89 +6378,345 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object type: object x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels @@ -6695,359 +6746,1766 @@ spec: required: - topologyKey type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight type: object - x-kubernetes-map-type: atomic - matchLabelKeys: + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic + type: array + x-kubernetes-list-type: atomic + type: object type: object - type: object - configuration: - description: |- - Projected volumes containing custom pgBackRest configuration. These files are mounted - under "/etc/pgbackrest/conf.d" alongside any pgBackRest configuration generated by the - PostgreSQL Operator: - https://pgbackrest.org/configuration.html - items: - description: |- - Projection that may be projected along with other supported volume types. - Exactly one of these fields must be set. - properties: - clusterTrustBundle: - description: |- - ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field - of ClusterTrustBundle objects in an auto-updating file. - - Alpha, gated by the ClusterTrustBundleProjection feature gate. - - ClusterTrustBundle objects can either be selected by name, or by the - combination of signer name and a label selector. - - Kubelet performs aggressive normalization of the PEM contents written - into the pod filesystem. Esoteric PEM features such as inter-block - comments and block headers are stripped. Certificates are deduplicated. - The ordering of certificates within the file is arbitrary, and Kubelet - may change the order over time. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. Mutually-exclusive with name. If unset, - interpreted as "match nothing". If set but empty, interpreted as "match - everything". + clusterName: + description: |- + The name of an existing PostgresCluster to use as the data source for the new PostgresCluster. + Defaults to the name of the PostgresCluster being created if not provided. + type: string + clusterNamespace: + description: |- + The namespace of the cluster specified as the data source using the clusterName field. + Defaults to the namespace of the PostgresCluster being created if not provided. + type: string + enabled: + default: false + description: Whether or not in-place pgBackRest restores + are enabled for this PostgresCluster. + type: boolean + options: + description: |- + Command line options to include when running the pgBackRest restore command. + https://pgbackrest.org/command.html#command-restore + items: + type: string + type: array + priorityClassName: + description: |- + Priority class name for the pgBackRest restore Job pod. Changing this + value causes PostgreSQL to restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + type: string + repoName: + description: |- + The name of the pgBackRest repo within the source PostgresCluster that contains the backups + that should be utilized to perform a pgBackRest restore when initializing the data source + for the new PostgresCluster. + pattern: ^repo[1-4] + type: string + resources: + description: Resource requirements for the pgBackRest + restore Job. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + name: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name type: object - x-kubernetes-map-type: atomic - name: + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + description: |- + Tolerations of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string - optional: + key: description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. If using name, then the named ClusterTrustBundle is - allowed not to exist. If using signerName, then the combination of - signerName and labelSelector is allowed to match zero - ClusterTrustBundles. - type: boolean - path: - description: Relative path from the volume root - to write the bundle. + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string - signerName: + operator: description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. The contents of all selected - ClusterTrustBundles will be unified and deduplicated. + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. type: string - required: - - path - type: object - configMap: - description: configMap information about the configMap - data to project - properties: - items: + tolerationSeconds: description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about the downwardAPI - data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file + type: array + required: + - enabled + - repoName + type: object + sidecars: + description: 'Deprecated: Use Containers instead' + properties: + pgbackrest: + description: Defines the configuration for the pgBackRest + sidecar container + properties: + resources: + description: Resource requirements for a sidecar container + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + pgbackrestConfig: + description: Defines the configuration for the pgBackRest + config sidecar container + properties: + resources: + description: Resource requirements for a sidecar container + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + type: object + required: + - repos + type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean + type: object + crVersion: + description: |- + Version of the operator. Update this to new version after operator + upgrade to apply changes to Kubernetes objects. Default is the latest + version. + type: string + dataSource: + description: Specifies a data source for bootstrapping the PostgreSQL + cluster. + properties: + pgbackrest: + description: |- + Defines a pgBackRest cloud-based data source that can be used to pre-populate the + PostgreSQL data directory for a new PostgreSQL cluster using a pgBackRest restore. + The PGBackRest field is incompatible with the PostgresCluster field: only one + data source can be used for pre-populating a new PostgreSQL cluster + properties: + affinity: + description: |- + Scheduling constraints of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + configuration: + description: |- + Projected volumes containing custom pgBackRest configuration. These files are mounted + under "/etc/pgbackrest/conf.d" alongside any pgBackRest configuration generated by the + PostgreSQL Operator: + https://pgbackrest.org/configuration.html + items: + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. + properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume root + to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file items: description: DownwardAPIVolumeFile represents information to create the file containing the @@ -28791,67 +30249,350 @@ spec: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in + the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string type: array x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. format: int32 type: integer required: - - preference + - podAffinityTerm - weight type: object type: array @@ -28861,42 +30602,49 @@ spec: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: - description: A list of node selector - requirements by node's labels. + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that - the selector applies to. + description: key is the label + key that the selector applies + to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -28907,30 +30655,77 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that - the selector applies to. + description: key is the label + key that the selector applies + to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -28941,28 +30736,53 @@ spec: type: object type: array x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). properties: preferredDuringSchedulingIgnoredDuringExecution: description: |- The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose + the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), + request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. @@ -29134,848 +30954,1944 @@ spec: format: int32 type: integer required: - - podAffinityTerm - - weight + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object type: array x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: + type: object + type: object + priorityClassName: + description: |- + Priority class name for the pgBackRest repo host pod. Changing this value + causes PostgreSQL to restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + type: string + resources: + description: Resource requirements for a pgBackRest repository + host + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + securityContext: + description: SecurityContext defines the security settings + for PGBackRest pod. + properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxChangePolicy: + description: |- + seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. + It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. + Valid values are "MountOption" and "Recursive". + + "Recursive" means relabeling of all files on all Pod volumes by the container runtime. + This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. + + "MountOption" mounts all eligible Pod volumes with `-o context` mount option. + This requires all Pods that share the same volume to use the same SELinux label. + It is not possible to share the same volume among privileged and unprivileged Pods. + Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes + whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their + CSIDriver instance. Other volumes are always re-labelled recursively. + "MountOption" value is allowed only when SELinuxMount feature gate is enabled. + + If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. + If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes + and "Recursive" for all other volumes. + + This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. + + All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. + Note that this field cannot be set when spec.os.name is windows. + type: string + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and fsGroup (if specified). If + the SupplementalGroupsPolicy feature is enabled, the + supplementalGroupsPolicy field determines whether these are in addition + to or instead of any group memberships defined in the container image. + If unspecified, no additional groups are added, though group memberships + defined in the container image may still be used, depending on the + supplementalGroupsPolicy field. + Note that this field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". If not specified, "Merge" is used. + (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled + and the container runtime must implement support for this feature. + Note that this field cannot be set when spec.os.name is windows. + type: string + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to + be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + sidecars: + description: |- + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. + items: + description: A single application container that you + want to run within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: + name: + default: "" description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. type: string required: - - topologyKey + - port type: object - weight: + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + exec: + description: Exec specifies a command to + execute in the container. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: + name: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic required: - - key - - operator + - name + - value type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - x-kubernetes-map-type: atomic - matchLabelKeys: + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - mismatchLabelKeys: + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. items: - type: string + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object type: array x-kubernetes-list-type: atomic - namespaceSelector: + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. type: string required: - - topologyKey + - type type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - priorityClassName: - description: |- - Priority class name for the pgBackRest repo host pod. Changing this value - causes PostgreSQL to restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ - type: string - resources: - description: Resource requirements for a pgBackRest repository - host - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: + windowsOptions: description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: SecurityContext defines the security settings - for PGBackRest pod. - properties: - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxChangePolicy: - description: |- - seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. - It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. - Valid values are "MountOption" and "Recursive". - - "Recursive" means relabeling of all files on all Pod volumes by the container runtime. - This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - "MountOption" mounts all eligible Pod volumes with `-o context` mount option. - This requires all Pods that share the same volume to use the same SELinux label. - It is not possible to share the same volume among privileged and unprivileged Pods. - Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes - whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their - CSIDriver instance. Other volumes are always re-labelled recursively. - "MountOption" value is allowed only when SELinuxMount feature gate is enabled. + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. - If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. - If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes - and "Recursive" for all other volumes. + If ReadOnly is false, this field has no meaning and must be unspecified. - This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. - All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. - Note that this field cannot be set when spec.os.name is windows. - type: string - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that - applies to the container. - type: string - role: - description: Role is a SELinux role label that - applies to the container. - type: string - type: - description: Type is a SELinux type label that - applies to the container. - type: string - user: - description: User is a SELinux user label that - applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in - addition to the container's primary GID and fsGroup (if specified). If - the SupplementalGroupsPolicy feature is enabled, the - supplementalGroupsPolicy field determines whether these are in addition - to or instead of any group memberships defined in the container image. - If unspecified, no additional groups are added, though group memberships - defined in the container image may still be used, depending on the - supplementalGroupsPolicy field. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - supplementalGroupsPolicy: - description: |- - Defines how supplemental groups of the first container processes are calculated. - Valid values are "Merge" and "Strict". If not specified, "Merge" is used. - (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled - and the container runtime must implement support for this feature. - Note that this field cannot be set when spec.os.name is windows. - type: string - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to - be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + type: array sshConfigMap: description: |- ConfigMap containing custom SSH configuration. diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 99d7ee2995..5e494820b4 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -496,6 +496,13 @@ spec: # repo3-path: /pgbackrest/postgres-operator/cluster1-multi-repo/repo3 # repo4-path: /pgbackrest/postgres-operator/cluster1-multi-repo/repo4 repoHost: +# sidecars: +# - name: testcontainer +# image: busybox:latest +# command: ["sleep", "30d"] +# securityContext: {} +# - name: testcontainer2 +# image: mycontainer1:latest # resources: # limits: # cpu: 200m diff --git a/deploy/crd.yaml b/deploy/crd.yaml index a08e9c33ac..52632fe0df 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -4084,1705 +4084,1615 @@ spec: type: string type: object type: object - sshConfigMap: - description: |- - ConfigMap containing custom SSH configuration. - Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - sshSecret: - description: |- - Secret containing custom SSH keys. - Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional field specify whether the Secret - or its key must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - tolerations: - description: |- - Tolerations of a PgBackRest repo host pod. Changing this value causes a restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: + sidecars: description: |- - Topology spread constraints of a Dedicated repo host pod. Changing this - value causes the repo host to restart. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. items: - description: TopologySpreadConstraint specifies how - to spread matching pods among the given topology. + description: A single application container that you + want to run within a pod. properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell items: type: string type: array x-kubernetes-list-type: atomic - maxSkew: + command: description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. type: string - nodeTaintsPolicy: + imagePullPolicy: description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images type: string - topologyKey: + lifecycle: description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - repos: - description: Defines a pgBackRest repository - items: - description: PGBackRestRepo represents a pgBackRest repository. Only - one of its members may be specified. - properties: - azure: - description: Represents a pgBackRest repository that - is created using Azure storage - properties: - container: - description: The Azure container utilized for the - repository - type: string - required: - - container - type: object - gcs: - description: Represents a pgBackRest repository that - is created using Google Cloud Storage - properties: - bucket: - description: The GCS bucket utilized for the repository - type: string - required: - - bucket - type: object - name: - description: The name of the repository - pattern: ^repo[1-4] - type: string - s3: - description: |- - RepoS3 represents a pgBackRest repository that is created using AWS S3 (or S3-compatible) - storage - properties: - bucket: - description: The S3 bucket utilized for the repository - type: string - endpoint: - description: A valid endpoint corresponding to the - specified region - type: string - region: - description: The region corresponding to the S3 - bucket - type: string - required: - - bucket - - endpoint - - region - type: object - schedules: - description: |- - Defines the schedules for the pgBackRest backups - Full, Differential and Incremental backup types are supported: - https://pgbackrest.org/user-guide.html#concept/backup - properties: - differential: - description: |- - Defines the Cron schedule for a differential pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - full: - description: |- - Defines the Cron schedule for a full pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - incremental: - description: |- - Defines the Cron schedule for an incremental pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - type: object - volume: - description: Represents a pgBackRest repository that - is created using a PersistentVolumeClaim - properties: - volumeClaimSpec: - description: Defines a PersistentVolumeClaim spec - used to create and/or bind a volume + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. properties: - apiGroup: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - - kind - - name + - port type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. properties: - apiGroup: + host: description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. type: string - name: - description: Name is the name of resource - being referenced + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. type: string - namespace: + port: + anyOf: + - type: integer + - type: string description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. type: string required: - - kind - - name + - port type: object - resources: + initialDelaySeconds: description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic type: object - selector: - description: selector is a label query over - volumes to consider for binding. + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + description: HTTPHeader describes a custom + header to be used in HTTP probes properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + name: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic required: - - key - - operator + - name + - value type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: + initialDelaySeconds: description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). - type: string - volumeMode: + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding reference - to the PersistentVolume backing this claim. - type: string - type: object - required: - - volumeClaimSpec - type: object - required: - - name - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restore: - description: Defines details for performing an in-place restore - using pgBackRest - properties: - affinity: - description: |- - Scheduling constraints of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. - format: int32 - type: integer + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true required: - - preference - - weight + - port type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string required: - - nodeSelectorTerms + - resourceName + - restartPolicy type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: + localhostProfile: description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string required: - - podAffinityTerm - - weight + - type type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: + capabilities: description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. + add: + description: Added capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + drop: + description: Removed capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - - topologyKey + - port type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: + value: + description: The header field value type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string required: - - podAffinityTerm - - weight + - port type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: + initialDelaySeconds: description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true required: - - topologyKey + - port type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - clusterName: - description: |- - The name of an existing PostgresCluster to use as the data source for the new PostgresCluster. - Defaults to the name of the PostgresCluster being created if not provided. - type: string - clusterNamespace: - description: |- - The namespace of the cluster specified as the data source using the clusterName field. - Defaults to the namespace of the PostgresCluster being created if not provided. - type: string - enabled: - default: false - description: Whether or not in-place pgBackRest restores - are enabled for this PostgresCluster. - type: boolean - options: - description: |- - Command line options to include when running the pgBackRest restore command. - https://pgbackrest.org/command.html#command-restore - items: - type: string + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object type: array - priorityClassName: - description: |- - Priority class name for the pgBackRest restore Job pod. Changing this - value causes PostgreSQL to restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ - type: string - repoName: + sshConfigMap: description: |- - The name of the pgBackRest repo within the source PostgresCluster that contains the backups - that should be utilized to perform a pgBackRest restore when initializing the data source - for the new PostgresCluster. - pattern: ^repo[1-4] - type: string - resources: - description: Resource requirements for the pgBackRest - restore Job. + ConfigMap containing custom SSH configuration. + Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. properties: - claims: + items: description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + description: Maps a string key to a path within + a volume. properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. + key: + description: key is the key to project. type: string - request: + mode: description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. type: string required: - - name + - key + - path type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + x-kubernetes-list-type: atomic + name: + default: "" description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean type: object - tolerations: + x-kubernetes-map-type: atomic + sshSecret: description: |- - Tolerations of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 + Secret containing custom SSH keys. + Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the Secret, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional field specify whether the Secret + or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + tolerations: + description: |- + Tolerations of a PgBackRest repo host pod. Changing this value causes a restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 type: integer value: description: |- @@ -5791,255 +5701,422 @@ spec: type: string type: object type: array - required: - - enabled - - repoName - type: object - sidecars: - description: 'Deprecated: Use Containers instead' - properties: - pgbackrest: - description: Defines the configuration for the pgBackRest - sidecar container - properties: - resources: - description: Resource requirements for a sidecar container - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name + topologySpreadConstraints: + description: |- + Topology spread constraints of a Dedicated repo host pod. Changing this + value causes the repo host to restart. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how + to spread matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - type: object - pgbackrestConfig: - description: Defines the configuration for the pgBackRest - config sidecar container - properties: - resources: - description: Resource requirements for a sidecar container - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + Keys that don't exist in the incoming pod labels will + be ignored. A null or empty list means only match against labelSelector. - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. + This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same + labelSelector spread as 2/2/1: + In this case, the global minimum is 1. + | zone1 | zone2 | zone3 | + | P P | P P | P | + - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; + scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) + violate MaxSkew(1). + - if MaxSkew is 2, incoming pod can be scheduled onto any zone. + When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence + to topologies that satisfy it. + It's a required field. Default value is 1 and 0 is not allowed. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + As a result, when the number of eligible domains is less than minDomains, + scheduler won't schedule more than maxSkew Pods to those domains. + If value is nil, the constraint behaves as if MinDomains is equal to 1. + Valid values are integers greater than 0. + When value is not nil, WhenUnsatisfiable must be DoNotSchedule. + + For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same + labelSelector spread as 2/2/2: + | zone1 | zone2 | zone3 | + | P P | P P | P P | + The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. + In this situation, new pod with the same labelSelector cannot be scheduled, + because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, + it will violate MaxSkew. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. + And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. + It's a required field. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same + labelSelector spread as 3/1/1: + | zone1 | zone2 | zone3 | + | P P P | P | P | + If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled + to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies + MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler + won't make it *more* imbalanced. + It's a required field. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + repos: + description: Defines a pgBackRest repository + items: + description: PGBackRestRepo represents a pgBackRest repository. Only + one of its members may be specified. + properties: + azure: + description: Represents a pgBackRest repository that + is created using Azure storage + properties: + container: + description: The Azure container utilized for the + repository + type: string + required: + - container + type: object + gcs: + description: Represents a pgBackRest repository that + is created using Google Cloud Storage + properties: + bucket: + description: The GCS bucket utilized for the repository + type: string + required: + - bucket + type: object + name: + description: The name of the repository + pattern: ^repo[1-4] + type: string + s3: + description: |- + RepoS3 represents a pgBackRest repository that is created using AWS S3 (or S3-compatible) + storage + properties: + bucket: + description: The S3 bucket utilized for the repository + type: string + endpoint: + description: A valid endpoint corresponding to the + specified region + type: string + region: + description: The region corresponding to the S3 + bucket + type: string + required: + - bucket + - endpoint + - region + type: object + schedules: + description: |- + Defines the schedules for the pgBackRest backups + Full, Differential and Incremental backup types are supported: + https://pgbackrest.org/user-guide.html#concept/backup + properties: + differential: + description: |- + Defines the Cron schedule for a differential pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + full: + description: |- + Defines the Cron schedule for a full pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + incremental: + description: |- + Defines the Cron schedule for an incremental pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + type: object + volume: + description: Represents a pgBackRest repository that + is created using a PersistentVolumeClaim + properties: + volumeClaimSpec: + description: Defines a PersistentVolumeClaim spec + used to create and/or bind a volume + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. + When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, + and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not be copied to dataSource. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced type: string required: + - kind - name type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - type: object - type: object - required: - - repos - type: object - trackLatestRestorableTime: - description: Enable tracking latest restorable time - type: boolean - type: object - crVersion: - description: |- - Version of the operator. Update this to new version after operator - upgrade to apply changes to Kubernetes objects. Default is the latest - version. - type: string - dataSource: - description: Specifies a data source for bootstrapping the PostgreSQL - cluster. - properties: - pgbackrest: - description: |- - Defines a pgBackRest cloud-based data source that can be used to pre-populate the - PostgreSQL data directory for a new PostgreSQL cluster using a pgBackRest restore. - The PGBackRest field is incompatible with the PostgresCluster field: only one - data source can be used for pre-populating a new PostgreSQL cluster - properties: - affinity: - description: |- - Scheduling constraints of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed if the type of + the specified object matches some installed volume populator or dynamic + provisioner. + This field will replace the functionality of the dataSource field and as such + if both fields are non-empty, they must have the same value. For backwards + compatibility, when namespace isn't specified in dataSourceRef, + both fields (dataSource and dataSourceRef) will be set to the same + value automatically if one of them is empty and the other is non-empty. + When namespace is specified in dataSourceRef, + dataSource isn't set to the same value and must be empty. + There are three important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping them), dataSourceRef + preserves all values, and generates an error if a disallowed value is + specified. + * While dataSource only allows local objects, dataSourceRef allows objects + in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that the - selector applies to. + description: key is the label key + that the selector applies to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -6050,169 +6127,114 @@ spec: type: object type: array x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in the - range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: + storageClassName: description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). + type: string + volumeMode: + description: |- + volumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - volumeClaimSpec + type: object + required: + - name + type: object + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Defines details for performing an in-place restore + using pgBackRest + properties: + affinity: + description: |- + Scheduling constraints of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + preference: + description: A node selector term, associated + with the corresponding weight. properties: matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + description: A list of node selector + requirements by node's labels. items: description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6223,79 +6245,32 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + matchFields: + description: A list of node selector + requirements by node's fields. items: description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string type: array x-kubernetes-list-type: atomic required: @@ -6304,275 +6279,95 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object type: object x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in + the range 1-100. + format: int32 + type: integer required: - - topologyKey + - preference + - weight type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6583,89 +6378,345 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object type: object x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels @@ -6695,359 +6746,1766 @@ spec: required: - topologyKey type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight type: object - x-kubernetes-map-type: atomic - matchLabelKeys: + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic + type: array + x-kubernetes-list-type: atomic + type: object type: object - type: object - configuration: - description: |- - Projected volumes containing custom pgBackRest configuration. These files are mounted - under "/etc/pgbackrest/conf.d" alongside any pgBackRest configuration generated by the - PostgreSQL Operator: - https://pgbackrest.org/configuration.html - items: - description: |- - Projection that may be projected along with other supported volume types. - Exactly one of these fields must be set. - properties: - clusterTrustBundle: - description: |- - ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field - of ClusterTrustBundle objects in an auto-updating file. - - Alpha, gated by the ClusterTrustBundleProjection feature gate. - - ClusterTrustBundle objects can either be selected by name, or by the - combination of signer name and a label selector. - - Kubelet performs aggressive normalization of the PEM contents written - into the pod filesystem. Esoteric PEM features such as inter-block - comments and block headers are stripped. Certificates are deduplicated. - The ordering of certificates within the file is arbitrary, and Kubelet - may change the order over time. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. Mutually-exclusive with name. If unset, - interpreted as "match nothing". If set but empty, interpreted as "match - everything". + clusterName: + description: |- + The name of an existing PostgresCluster to use as the data source for the new PostgresCluster. + Defaults to the name of the PostgresCluster being created if not provided. + type: string + clusterNamespace: + description: |- + The namespace of the cluster specified as the data source using the clusterName field. + Defaults to the namespace of the PostgresCluster being created if not provided. + type: string + enabled: + default: false + description: Whether or not in-place pgBackRest restores + are enabled for this PostgresCluster. + type: boolean + options: + description: |- + Command line options to include when running the pgBackRest restore command. + https://pgbackrest.org/command.html#command-restore + items: + type: string + type: array + priorityClassName: + description: |- + Priority class name for the pgBackRest restore Job pod. Changing this + value causes PostgreSQL to restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + type: string + repoName: + description: |- + The name of the pgBackRest repo within the source PostgresCluster that contains the backups + that should be utilized to perform a pgBackRest restore when initializing the data source + for the new PostgresCluster. + pattern: ^repo[1-4] + type: string + resources: + description: Resource requirements for the pgBackRest + restore Job. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + name: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name type: object - x-kubernetes-map-type: atomic - name: + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + description: |- + Tolerations of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string - optional: + key: description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. If using name, then the named ClusterTrustBundle is - allowed not to exist. If using signerName, then the combination of - signerName and labelSelector is allowed to match zero - ClusterTrustBundles. - type: boolean - path: - description: Relative path from the volume root - to write the bundle. + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string - signerName: + operator: description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. The contents of all selected - ClusterTrustBundles will be unified and deduplicated. + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. type: string - required: - - path - type: object - configMap: - description: configMap information about the configMap - data to project - properties: - items: + tolerationSeconds: description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about the downwardAPI - data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file + type: array + required: + - enabled + - repoName + type: object + sidecars: + description: 'Deprecated: Use Containers instead' + properties: + pgbackrest: + description: Defines the configuration for the pgBackRest + sidecar container + properties: + resources: + description: Resource requirements for a sidecar container + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + pgbackrestConfig: + description: Defines the configuration for the pgBackRest + config sidecar container + properties: + resources: + description: Resource requirements for a sidecar container + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + type: object + required: + - repos + type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean + type: object + crVersion: + description: |- + Version of the operator. Update this to new version after operator + upgrade to apply changes to Kubernetes objects. Default is the latest + version. + type: string + dataSource: + description: Specifies a data source for bootstrapping the PostgreSQL + cluster. + properties: + pgbackrest: + description: |- + Defines a pgBackRest cloud-based data source that can be used to pre-populate the + PostgreSQL data directory for a new PostgreSQL cluster using a pgBackRest restore. + The PGBackRest field is incompatible with the PostgresCluster field: only one + data source can be used for pre-populating a new PostgreSQL cluster + properties: + affinity: + description: |- + Scheduling constraints of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + configuration: + description: |- + Projected volumes containing custom pgBackRest configuration. These files are mounted + under "/etc/pgbackrest/conf.d" alongside any pgBackRest configuration generated by the + PostgreSQL Operator: + https://pgbackrest.org/configuration.html + items: + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. + properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume root + to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file items: description: DownwardAPIVolumeFile represents information to create the file containing the @@ -28791,67 +30249,350 @@ spec: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in + the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string type: array x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. format: int32 type: integer required: - - preference + - podAffinityTerm - weight type: object type: array @@ -28861,42 +30602,49 @@ spec: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: - description: A list of node selector - requirements by node's labels. + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that - the selector applies to. + description: key is the label + key that the selector applies + to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -28907,30 +30655,77 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that - the selector applies to. + description: key is the label + key that the selector applies + to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -28941,28 +30736,53 @@ spec: type: object type: array x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). properties: preferredDuringSchedulingIgnoredDuringExecution: description: |- The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose + the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), + request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. @@ -29134,848 +30954,1944 @@ spec: format: int32 type: integer required: - - podAffinityTerm - - weight + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object type: array x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: + type: object + type: object + priorityClassName: + description: |- + Priority class name for the pgBackRest repo host pod. Changing this value + causes PostgreSQL to restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + type: string + resources: + description: Resource requirements for a pgBackRest repository + host + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + securityContext: + description: SecurityContext defines the security settings + for PGBackRest pod. + properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxChangePolicy: + description: |- + seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. + It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. + Valid values are "MountOption" and "Recursive". + + "Recursive" means relabeling of all files on all Pod volumes by the container runtime. + This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. + + "MountOption" mounts all eligible Pod volumes with `-o context` mount option. + This requires all Pods that share the same volume to use the same SELinux label. + It is not possible to share the same volume among privileged and unprivileged Pods. + Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes + whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their + CSIDriver instance. Other volumes are always re-labelled recursively. + "MountOption" value is allowed only when SELinuxMount feature gate is enabled. + + If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. + If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes + and "Recursive" for all other volumes. + + This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. + + All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. + Note that this field cannot be set when spec.os.name is windows. + type: string + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and fsGroup (if specified). If + the SupplementalGroupsPolicy feature is enabled, the + supplementalGroupsPolicy field determines whether these are in addition + to or instead of any group memberships defined in the container image. + If unspecified, no additional groups are added, though group memberships + defined in the container image may still be used, depending on the + supplementalGroupsPolicy field. + Note that this field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". If not specified, "Merge" is used. + (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled + and the container runtime must implement support for this feature. + Note that this field cannot be set when spec.os.name is windows. + type: string + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to + be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + sidecars: + description: |- + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. + items: + description: A single application container that you + want to run within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: + name: + default: "" description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. type: string required: - - topologyKey + - port type: object - weight: + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + exec: + description: Exec specifies a command to + execute in the container. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: + name: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic required: - - key - - operator + - name + - value type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - x-kubernetes-map-type: atomic - matchLabelKeys: + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - mismatchLabelKeys: + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. items: - type: string + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object type: array x-kubernetes-list-type: atomic - namespaceSelector: + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. type: string required: - - topologyKey + - type type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - priorityClassName: - description: |- - Priority class name for the pgBackRest repo host pod. Changing this value - causes PostgreSQL to restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ - type: string - resources: - description: Resource requirements for a pgBackRest repository - host - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: + windowsOptions: description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: SecurityContext defines the security settings - for PGBackRest pod. - properties: - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxChangePolicy: - description: |- - seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. - It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. - Valid values are "MountOption" and "Recursive". - - "Recursive" means relabeling of all files on all Pod volumes by the container runtime. - This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - "MountOption" mounts all eligible Pod volumes with `-o context` mount option. - This requires all Pods that share the same volume to use the same SELinux label. - It is not possible to share the same volume among privileged and unprivileged Pods. - Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes - whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their - CSIDriver instance. Other volumes are always re-labelled recursively. - "MountOption" value is allowed only when SELinuxMount feature gate is enabled. + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. - If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. - If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes - and "Recursive" for all other volumes. + If ReadOnly is false, this field has no meaning and must be unspecified. - This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. - All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. - Note that this field cannot be set when spec.os.name is windows. - type: string - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that - applies to the container. - type: string - role: - description: Role is a SELinux role label that - applies to the container. - type: string - type: - description: Type is a SELinux type label that - applies to the container. - type: string - user: - description: User is a SELinux user label that - applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in - addition to the container's primary GID and fsGroup (if specified). If - the SupplementalGroupsPolicy feature is enabled, the - supplementalGroupsPolicy field determines whether these are in addition - to or instead of any group memberships defined in the container image. - If unspecified, no additional groups are added, though group memberships - defined in the container image may still be used, depending on the - supplementalGroupsPolicy field. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - supplementalGroupsPolicy: - description: |- - Defines how supplemental groups of the first container processes are calculated. - Valid values are "Merge" and "Strict". If not specified, "Merge" is used. - (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled - and the container runtime must implement support for this feature. - Note that this field cannot be set when spec.os.name is windows. - type: string - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to - be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + type: array sshConfigMap: description: |- ConfigMap containing custom SSH configuration. diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 1d1eb034c8..a7f1f1c494 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -4084,1705 +4084,1615 @@ spec: type: string type: object type: object - sshConfigMap: - description: |- - ConfigMap containing custom SSH configuration. - Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - sshSecret: - description: |- - Secret containing custom SSH keys. - Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. - properties: - items: - description: |- - items if unspecified, each key-value pair in the Data field of the referenced - Secret will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: optional field specify whether the Secret - or its key must be defined - type: boolean - type: object - x-kubernetes-map-type: atomic - tolerations: - description: |- - Tolerations of a PgBackRest repo host pod. Changing this value causes a restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - topologySpreadConstraints: + sidecars: description: |- - Topology spread constraints of a Dedicated repo host pod. Changing this - value causes the repo host to restart. - More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. items: - description: TopologySpreadConstraint specifies how - to spread matching pods among the given topology. + description: A single application container that you + want to run within a pod. properties: - labelSelector: - description: |- - LabelSelector is used to find matching pods. - Pods that match this label selector are counted to determine the number of pods - in their corresponding topology domain. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select the pods over which - spreading will be calculated. The keys are used to lookup values from the - incoming pod labels, those key-value labels are ANDed with labelSelector - to select the group of existing pods over which spreading will be calculated - for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - MatchLabelKeys cannot be set when LabelSelector isn't set. - Keys that don't exist in the incoming pod labels will - be ignored. A null or empty list means only match against labelSelector. - - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell items: type: string type: array x-kubernetes-list-type: atomic - maxSkew: + command: description: |- - MaxSkew describes the degree to which pods may be unevenly distributed. - When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference - between the number of matching pods in the target topology and the global minimum. - The global minimum is the minimum number of matching pods in an eligible domain - or zero if the number of eligible domains is less than MinDomains. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 2/2/1: - In this case, the global minimum is 1. - | zone1 | zone2 | zone3 | - | P P | P P | P | - - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; - scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) - violate MaxSkew(1). - - if MaxSkew is 2, incoming pod can be scheduled onto any zone. - When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence - to topologies that satisfy it. - It's a required field. Default value is 1 and 0 is not allowed. - format: int32 - type: integer - minDomains: + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: description: |- - MinDomains indicates a minimum number of eligible domains. - When the number of eligible domains with matching topology keys is less than minDomains, - Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. - And when the number of eligible domains with matching topology keys equals or greater than minDomains, - this value has no effect on scheduling. - As a result, when the number of eligible domains is less than minDomains, - scheduler won't schedule more than maxSkew Pods to those domains. - If value is nil, the constraint behaves as if MinDomains is equal to 1. - Valid values are integers greater than 0. - When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same - labelSelector spread as 2/2/2: - | zone1 | zone2 | zone3 | - | P P | P P | P P | - The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. - In this situation, new pod with the same labelSelector cannot be scheduled, - because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, - it will violate MaxSkew. - format: int32 - type: integer - nodeAffinityPolicy: + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: description: |- - NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector - when calculating pod topology spread skew. Options are: - - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - - If this value is nil, the behavior is equivalent to the Honor policy. + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. type: string - nodeTaintsPolicy: + imagePullPolicy: description: |- - NodeTaintsPolicy indicates how we will treat node taints when calculating - pod topology spread skew. Options are: - - Honor: nodes without taints, along with tainted nodes for which the incoming pod - has a toleration, are included. - - Ignore: node taints are ignored. All nodes are included. - - If this value is nil, the behavior is equivalent to the Ignore policy. + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images type: string - topologyKey: + lifecycle: description: |- - TopologyKey is the key of node labels. Nodes that have a label with this key - and identical values are considered to be in the same topology. - We consider each as a "bucket", and try to put balanced number - of pods into each bucket. - We define a domain as a particular instance of a topology. - Also, we define an eligible domain as a domain whose nodes meet the requirements of - nodeAffinityPolicy and nodeTaintsPolicy. - e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. - And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. - It's a required field. - type: string - whenUnsatisfiable: + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: description: |- - WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy - the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule it. - - ScheduleAnyway tells the scheduler to schedule the pod in any location, - but giving higher precedence to topologies that would help reduce the - skew. - A constraint is considered "Unsatisfiable" for an incoming pod - if and only if every possible node assignment for that pod would violate - "MaxSkew" on some topology. - For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same - labelSelector spread as 3/1/1: - | zone1 | zone2 | zone3 | - | P P P | P | P | - If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled - to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies - MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler - won't make it *more* imbalanced. - It's a required field. - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - type: object - repos: - description: Defines a pgBackRest repository - items: - description: PGBackRestRepo represents a pgBackRest repository. Only - one of its members may be specified. - properties: - azure: - description: Represents a pgBackRest repository that - is created using Azure storage - properties: - container: - description: The Azure container utilized for the - repository - type: string - required: - - container - type: object - gcs: - description: Represents a pgBackRest repository that - is created using Google Cloud Storage - properties: - bucket: - description: The GCS bucket utilized for the repository - type: string - required: - - bucket - type: object - name: - description: The name of the repository - pattern: ^repo[1-4] - type: string - s3: - description: |- - RepoS3 represents a pgBackRest repository that is created using AWS S3 (or S3-compatible) - storage - properties: - bucket: - description: The S3 bucket utilized for the repository - type: string - endpoint: - description: A valid endpoint corresponding to the - specified region - type: string - region: - description: The region corresponding to the S3 - bucket - type: string - required: - - bucket - - endpoint - - region - type: object - schedules: - description: |- - Defines the schedules for the pgBackRest backups - Full, Differential and Incremental backup types are supported: - https://pgbackrest.org/user-guide.html#concept/backup - properties: - differential: - description: |- - Defines the Cron schedule for a differential pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - full: - description: |- - Defines the Cron schedule for a full pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - incremental: - description: |- - Defines the Cron schedule for an incremental pgBackRest backup. - Follows the standard Cron schedule syntax: - https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax - minLength: 6 - type: string - type: object - volume: - description: Represents a pgBackRest repository that - is created using a PersistentVolumeClaim - properties: - volumeClaimSpec: - description: Defines a PersistentVolumeClaim spec - used to create and/or bind a volume + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes properties: - accessModes: - description: |- - accessModes contains the desired access modes the volume should have. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: description: |- - dataSource field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) - * An existing PVC (PersistentVolumeClaim) - If the provisioner or an external controller can support the specified data source, - it will create a new volume based on the contents of the specified data source. - When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, - and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. - If the namespace is specified, then dataSourceRef will not be copied to dataSource. + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. properties: - apiGroup: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced - type: string - name: - description: Name is the name of resource - being referenced + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - - kind - - name + - port type: object - x-kubernetes-map-type: atomic - dataSourceRef: - description: |- - dataSourceRef specifies the object from which to populate the volume with data, if a non-empty - volume is desired. This may be any object from a non-empty API group (non - core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only succeed if the type of - the specified object matches some installed volume populator or dynamic - provisioner. - This field will replace the functionality of the dataSource field and as such - if both fields are non-empty, they must have the same value. For backwards - compatibility, when namespace isn't specified in dataSourceRef, - both fields (dataSource and dataSourceRef) will be set to the same - value automatically if one of them is empty and the other is non-empty. - When namespace is specified in dataSourceRef, - dataSource isn't set to the same value and must be empty. - There are three important differences between dataSource and dataSourceRef: - * While dataSource only allows two specific types of objects, dataSourceRef - allows any non-core object, as well as PersistentVolumeClaim objects. - * While dataSource ignores disallowed values (dropping them), dataSourceRef - preserves all values, and generates an error if a disallowed value is - specified. - * While dataSource only allows local objects, dataSourceRef allows objects - in any namespaces. - (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. - (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. properties: - apiGroup: + host: description: |- - APIGroup is the group for the resource being referenced. - If APIGroup is not specified, the specified Kind must be in the core API group. - For any other third-party types, APIGroup is required. - type: string - kind: - description: Kind is the type of resource - being referenced + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. type: string - name: - description: Name is the name of resource - being referenced + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. type: string - namespace: + port: + anyOf: + - type: integer + - type: string description: |- - Namespace is the namespace of resource being referenced - Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. - (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. type: string required: - - kind - - name + - port type: object - resources: + initialDelaySeconds: description: |- - resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements - that are lower than previous value but must still be higher than capacity recorded in the - status field of the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic type: object - selector: - description: selector is a label query over - volumes to consider for binding. + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + description: HTTPHeader describes a custom + header to be used in HTTP probes properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + name: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic required: - - key - - operator + - name + - value type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - x-kubernetes-map-type: atomic - storageClassName: - description: |- - storageClassName is the name of the StorageClass required by the claim. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 - type: string - volumeAttributesClassName: + initialDelaySeconds: description: |- - volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. - If specified, the CSI driver will create or update the volume with the attributes defined - in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. - If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be - set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource - exists. - More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). - type: string - volumeMode: + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: description: |- - volumeMode defines what type of volume is required by the claim. - Value of Filesystem is implied when not included in claim spec. - type: string - volumeName: - description: volumeName is the binding reference - to the PersistentVolume backing this claim. - type: string - type: object - required: - - volumeClaimSpec - type: object - required: - - name - type: object - minItems: 1 - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - restore: - description: Defines details for performing an in-place restore - using pgBackRest - properties: - affinity: - description: |- - Scheduling constraints of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - preference: - description: A node selector term, associated - with the corresponding weight. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. - format: int32 - type: integer + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true required: - - preference - - weight + - port type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector - requirements by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string required: - - nodeSelectorTerms + - resourceName + - restartPolicy type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: + localhostProfile: description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string required: - - podAffinityTerm - - weight + - type type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: + capabilities: description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. + add: + description: Added capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + drop: + description: Removed capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. type: string required: - - topologyKey + - port type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: + value: + description: The header field value type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string required: - - podAffinityTerm - - weight + - port type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: + initialDelaySeconds: description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true required: - - topologyKey + - port type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - clusterName: - description: |- - The name of an existing PostgresCluster to use as the data source for the new PostgresCluster. - Defaults to the name of the PostgresCluster being created if not provided. - type: string - clusterNamespace: - description: |- - The namespace of the cluster specified as the data source using the clusterName field. - Defaults to the namespace of the PostgresCluster being created if not provided. - type: string - enabled: - default: false - description: Whether or not in-place pgBackRest restores - are enabled for this PostgresCluster. - type: boolean - options: - description: |- - Command line options to include when running the pgBackRest restore command. - https://pgbackrest.org/command.html#command-restore - items: - type: string + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object type: array - priorityClassName: - description: |- - Priority class name for the pgBackRest restore Job pod. Changing this - value causes PostgreSQL to restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ - type: string - repoName: + sshConfigMap: description: |- - The name of the pgBackRest repo within the source PostgresCluster that contains the backups - that should be utilized to perform a pgBackRest restore when initializing the data source - for the new PostgresCluster. - pattern: ^repo[1-4] - type: string - resources: - description: Resource requirements for the pgBackRest - restore Job. + ConfigMap containing custom SSH configuration. + Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. properties: - claims: + items: description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. + description: Maps a string key to a path within + a volume. properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. + key: + description: key is the key to project. type: string - request: + mode: description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. type: string required: - - name + - key + - path type: object type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true + x-kubernetes-list-type: atomic + name: + default: "" description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean type: object - tolerations: + x-kubernetes-map-type: atomic + sshSecret: description: |- - Tolerations of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 + Secret containing custom SSH keys. + Deprecated: Repository hosts use mTLS for encryption, authentication, and authorization. + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + Secret will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the Secret, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional field specify whether the Secret + or its key must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + tolerations: + description: |- + Tolerations of a PgBackRest repo host pod. Changing this value causes a restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 type: integer value: description: |- @@ -5791,255 +5701,422 @@ spec: type: string type: object type: array - required: - - enabled - - repoName - type: object - sidecars: - description: 'Deprecated: Use Containers instead' - properties: - pgbackrest: - description: Defines the configuration for the pgBackRest - sidecar container - properties: - resources: - description: Resource requirements for a sidecar container - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name + topologySpreadConstraints: + description: |- + Topology spread constraints of a Dedicated repo host pod. Changing this + value causes the repo host to restart. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + items: + description: TopologySpreadConstraint specifies how + to spread matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - type: object - pgbackrestConfig: - description: Defines the configuration for the pgBackRest - config sidecar container - properties: - resources: - description: Resource requirements for a sidecar container - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + Keys that don't exist in the incoming pod labels will + be ignored. A null or empty list means only match against labelSelector. - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. + This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same + labelSelector spread as 2/2/1: + In this case, the global minimum is 1. + | zone1 | zone2 | zone3 | + | P P | P P | P | + - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; + scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) + violate MaxSkew(1). + - if MaxSkew is 2, incoming pod can be scheduled onto any zone. + When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence + to topologies that satisfy it. + It's a required field. Default value is 1 and 0 is not allowed. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + As a result, when the number of eligible domains is less than minDomains, + scheduler won't schedule more than maxSkew Pods to those domains. + If value is nil, the constraint behaves as if MinDomains is equal to 1. + Valid values are integers greater than 0. + When value is not nil, WhenUnsatisfiable must be DoNotSchedule. + + For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same + labelSelector spread as 2/2/2: + | zone1 | zone2 | zone3 | + | P P | P P | P P | + The number of domains is less than 5(MinDomains), so "global minimum" is treated as 0. + In this situation, new pod with the same labelSelector cannot be scheduled, + because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, + it will violate MaxSkew. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. + And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. + It's a required field. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same + labelSelector spread as 3/1/1: + | zone1 | zone2 | zone3 | + | P P P | P | P | + If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled + to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies + MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler + won't make it *more* imbalanced. + It's a required field. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + repos: + description: Defines a pgBackRest repository + items: + description: PGBackRestRepo represents a pgBackRest repository. Only + one of its members may be specified. + properties: + azure: + description: Represents a pgBackRest repository that + is created using Azure storage + properties: + container: + description: The Azure container utilized for the + repository + type: string + required: + - container + type: object + gcs: + description: Represents a pgBackRest repository that + is created using Google Cloud Storage + properties: + bucket: + description: The GCS bucket utilized for the repository + type: string + required: + - bucket + type: object + name: + description: The name of the repository + pattern: ^repo[1-4] + type: string + s3: + description: |- + RepoS3 represents a pgBackRest repository that is created using AWS S3 (or S3-compatible) + storage + properties: + bucket: + description: The S3 bucket utilized for the repository + type: string + endpoint: + description: A valid endpoint corresponding to the + specified region + type: string + region: + description: The region corresponding to the S3 + bucket + type: string + required: + - bucket + - endpoint + - region + type: object + schedules: + description: |- + Defines the schedules for the pgBackRest backups + Full, Differential and Incremental backup types are supported: + https://pgbackrest.org/user-guide.html#concept/backup + properties: + differential: + description: |- + Defines the Cron schedule for a differential pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + full: + description: |- + Defines the Cron schedule for a full pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + incremental: + description: |- + Defines the Cron schedule for an incremental pgBackRest backup. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + type: object + volume: + description: Represents a pgBackRest repository that + is created using a PersistentVolumeClaim + properties: + volumeClaimSpec: + description: Defines a PersistentVolumeClaim spec + used to create and/or bind a volume + properties: + accessModes: + description: |- + accessModes contains the desired access modes the volume should have. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1 + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + description: |- + dataSource field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller can support the specified data source, + it will create a new volume based on the contents of the specified data source. + When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, + and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef will not be copied to dataSource. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced type: string required: + - kind - name type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - type: object - type: object - required: - - repos - type: object - trackLatestRestorableTime: - description: Enable tracking latest restorable time - type: boolean - type: object - crVersion: - description: |- - Version of the operator. Update this to new version after operator - upgrade to apply changes to Kubernetes objects. Default is the latest - version. - type: string - dataSource: - description: Specifies a data source for bootstrapping the PostgreSQL - cluster. - properties: - pgbackrest: - description: |- - Defines a pgBackRest cloud-based data source that can be used to pre-populate the - PostgreSQL data directory for a new PostgreSQL cluster using a pgBackRest restore. - The PGBackRest field is incompatible with the PostgresCluster field: only one - data source can be used for pre-populating a new PostgreSQL cluster - properties: - affinity: - description: |- - Scheduling constraints of the pgBackRest restore Job. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node - properties: - nodeAffinity: - description: Describes node affinity scheduling rules - for the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated - with the corresponding weight. + x-kubernetes-map-type: atomic + dataSourceRef: + description: |- + dataSourceRef specifies the object from which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding will only succeed if the type of + the specified object matches some installed volume populator or dynamic + provisioner. + This field will replace the functionality of the dataSource field and as such + if both fields are non-empty, they must have the same value. For backwards + compatibility, when namespace isn't specified in dataSourceRef, + both fields (dataSource and dataSourceRef) will be set to the same + value automatically if one of them is empty and the other is non-empty. + When namespace is specified in dataSourceRef, + dataSource isn't set to the same value and must be empty. + There are three important differences between dataSource and dataSourceRef: + * While dataSource only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values (dropping them), dataSourceRef + preserves all values, and generates an error if a disallowed value is + specified. + * While dataSource only allows local objects, dataSourceRef allows objects + in any namespaces. + (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. + (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + properties: + apiGroup: + description: |- + APIGroup is the group for the resource being referenced. + If APIGroup is not specified, the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: |- + Namespace is the namespace of resource being referenced + Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. + (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: |- + resources represents the minimum resources the volume should have. + If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + that are lower than previous value but must still be higher than capacity recorded in the + status field of the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that the - selector applies to. + description: key is the label key + that the selector applies to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -6050,169 +6127,114 @@ spec: type: object type: array x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in the - range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: + storageClassName: description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the - selector applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). + storageClassName is the name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1 + type: string + volumeAttributesClassName: + description: |- + volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. + If specified, the CSI driver will create or update the volume with the attributes defined + in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, + it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it's not allowed to reset this field to empty string once it is set. + If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller if it exists. + If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be + set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource + exists. + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). + type: string + volumeMode: + description: |- + volumeMode defines what type of volume is required by the claim. + Value of Filesystem is implied when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - volumeClaimSpec + type: object + required: + - name + type: object + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Defines details for performing an in-place restore + using pgBackRest + properties: + affinity: + description: |- + Scheduling constraints of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + preference: + description: A node selector term, associated + with the corresponding weight. properties: matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + description: A list of node selector + requirements by node's labels. items: description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6223,79 +6245,32 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + matchFields: + description: A list of node selector + requirements by node's fields. items: description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string type: array x-kubernetes-list-type: atomic required: @@ -6304,275 +6279,95 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object type: object x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in + the range 1-100. + format: int32 + type: integer required: - - topologyKey + - preference + - weight type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, - etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. properties: key: - description: key is the label - key that the selector applies - to. + description: The label key that + the selector applies to. type: string operator: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string values: description: |- - values is an array of string values. If the operator is In or NotIn, + An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. items: type: string type: array @@ -6583,89 +6378,345 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object type: object x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string description: |- matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels @@ -6695,359 +6746,1766 @@ spec: required: - topologyKey type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight type: object - x-kubernetes-map-type: atomic - matchLabelKeys: + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic + type: array + x-kubernetes-list-type: atomic + type: object type: object - type: object - configuration: - description: |- - Projected volumes containing custom pgBackRest configuration. These files are mounted - under "/etc/pgbackrest/conf.d" alongside any pgBackRest configuration generated by the - PostgreSQL Operator: - https://pgbackrest.org/configuration.html - items: - description: |- - Projection that may be projected along with other supported volume types. - Exactly one of these fields must be set. - properties: - clusterTrustBundle: - description: |- - ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field - of ClusterTrustBundle objects in an auto-updating file. - - Alpha, gated by the ClusterTrustBundleProjection feature gate. - - ClusterTrustBundle objects can either be selected by name, or by the - combination of signer name and a label selector. - - Kubelet performs aggressive normalization of the PEM contents written - into the pod filesystem. Esoteric PEM features such as inter-block - comments and block headers are stripped. Certificates are deduplicated. - The ordering of certificates within the file is arbitrary, and Kubelet - may change the order over time. - properties: - labelSelector: - description: |- - Select all ClusterTrustBundles that match this label selector. Only has - effect if signerName is set. Mutually-exclusive with name. If unset, - interpreted as "match nothing". If set but empty, interpreted as "match - everything". + clusterName: + description: |- + The name of an existing PostgresCluster to use as the data source for the new PostgresCluster. + Defaults to the name of the PostgresCluster being created if not provided. + type: string + clusterNamespace: + description: |- + The namespace of the cluster specified as the data source using the clusterName field. + Defaults to the namespace of the PostgresCluster being created if not provided. + type: string + enabled: + default: false + description: Whether or not in-place pgBackRest restores + are enabled for this PostgresCluster. + type: boolean + options: + description: |- + Command line options to include when running the pgBackRest restore command. + https://pgbackrest.org/command.html#command-restore + items: + type: string + type: array + priorityClassName: + description: |- + Priority class name for the pgBackRest restore Job pod. Changing this + value causes PostgreSQL to restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + type: string + repoName: + description: |- + The name of the pgBackRest repo within the source PostgresCluster that contains the backups + that should be utilized to perform a pgBackRest restore when initializing the data source + for the new PostgresCluster. + pattern: ^repo[1-4] + type: string + resources: + description: Resource requirements for the pgBackRest + restore Job. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + name: description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name type: object - x-kubernetes-map-type: atomic - name: + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + description: |- + Tolerations of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: description: |- - Select a single ClusterTrustBundle by object name. Mutually-exclusive - with signerName and labelSelector. + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. type: string - optional: + key: description: |- - If true, don't block pod startup if the referenced ClusterTrustBundle(s) - aren't available. If using name, then the named ClusterTrustBundle is - allowed not to exist. If using signerName, then the combination of - signerName and labelSelector is allowed to match zero - ClusterTrustBundles. - type: boolean - path: - description: Relative path from the volume root - to write the bundle. + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. type: string - signerName: + operator: description: |- - Select all ClusterTrustBundles that match this signer name. - Mutually-exclusive with name. The contents of all selected - ClusterTrustBundles will be unified and deduplicated. + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. type: string - required: - - path - type: object - configMap: - description: configMap information about the configMap - data to project - properties: - items: + tolerationSeconds: description: |- - items if unspecified, each key-value pair in the Data field of the referenced - ConfigMap will be projected into the volume as a file whose name is the - key and content is the value. If specified, the listed keys will be - projected into the specified paths, and unlisted keys will not be - present. If a key is specified which is not present in the ConfigMap, - the volume setup will error unless it is marked optional. Paths must be - relative and may not contain the '..' path or start with '..'. - items: - description: Maps a string key to a path within - a volume. - properties: - key: - description: key is the key to project. - type: string - mode: - description: |- - mode is Optional: mode bits used to set permissions on this file. - Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. - YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. - If not specified, the volume defaultMode will be used. - This might be in conflict with other options that affect the file - mode, like fsGroup, and the result can be other mode bits set. - format: int32 - type: integer - path: - description: |- - path is the relative path of the file to map the key to. - May not be an absolute path. - May not contain the path element '..'. - May not start with the string '..'. - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. type: string - optional: - description: optional specify whether the ConfigMap - or its keys must be defined - type: boolean type: object - x-kubernetes-map-type: atomic - downwardAPI: - description: downwardAPI information about the downwardAPI - data to project - properties: - items: - description: Items is a list of DownwardAPIVolume - file + type: array + required: + - enabled + - repoName + type: object + sidecars: + description: 'Deprecated: Use Containers instead' + properties: + pgbackrest: + description: Defines the configuration for the pgBackRest + sidecar container + properties: + resources: + description: Resource requirements for a sidecar container + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + pgbackrestConfig: + description: Defines the configuration for the pgBackRest + config sidecar container + properties: + resources: + description: Resource requirements for a sidecar container + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + type: object + type: object + required: + - repos + type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean + type: object + crVersion: + description: |- + Version of the operator. Update this to new version after operator + upgrade to apply changes to Kubernetes objects. Default is the latest + version. + type: string + dataSource: + description: Specifies a data source for bootstrapping the PostgreSQL + cluster. + properties: + pgbackrest: + description: |- + Defines a pgBackRest cloud-based data source that can be used to pre-populate the + PostgreSQL data directory for a new PostgreSQL cluster using a pgBackRest restore. + The PGBackRest field is incompatible with the PostgresCluster field: only one + data source can be used for pre-populating a new PostgreSQL cluster + properties: + affinity: + description: |- + Scheduling constraints of the pgBackRest restore Job. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + configuration: + description: |- + Projected volumes containing custom pgBackRest configuration. These files are mounted + under "/etc/pgbackrest/conf.d" alongside any pgBackRest configuration generated by the + PostgreSQL Operator: + https://pgbackrest.org/configuration.html + items: + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. + properties: + clusterTrustBundle: + description: |- + ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating file. + + Alpha, gated by the ClusterTrustBundleProjection feature gate. + + ClusterTrustBundle objects can either be selected by name, or by the + combination of signer name and a label selector. + + Kubelet performs aggressive normalization of the PEM contents written + into the pod filesystem. Esoteric PEM features such as inter-block + comments and block headers are stripped. Certificates are deduplicated. + The ordering of certificates within the file is arbitrary, and Kubelet + may change the order over time. + properties: + labelSelector: + description: |- + Select all ClusterTrustBundles that match this label selector. Only has + effect if signerName is set. Mutually-exclusive with name. If unset, + interpreted as "match nothing". If set but empty, interpreted as "match + everything". + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: |- + Select a single ClusterTrustBundle by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: |- + If true, don't block pod startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the named ClusterTrustBundle is + allowed not to exist. If using signerName, then the combination of + signerName and labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume root + to write the bundle. + type: string + signerName: + description: |- + Select all ClusterTrustBundles that match this signer name. + Mutually-exclusive with name. The contents of all selected + ClusterTrustBundles will be unified and deduplicated. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: |- + items if unspecified, each key-value pair in the Data field of the referenced + ConfigMap will be projected into the volume as a file whose name is the + key and content is the value. If specified, the listed keys will be + projected into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: |- + mode is Optional: mode bits used to set permissions on this file. + Must be an octal value between 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. + If not specified, the volume defaultMode will be used. + This might be in conflict with other options that affect the file + mode, like fsGroup, and the result can be other mode bits set. + format: int32 + type: integer + path: + description: |- + path is the relative path of the file to map the key to. + May not be an absolute path. + May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + description: downwardAPI information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file items: description: DownwardAPIVolumeFile represents information to create the file containing the @@ -28791,67 +30249,350 @@ spec: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in + the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that + the selector applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules + (e.g. co-locate this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added per-node + to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string type: array x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that - the selector applies to. - type: string - operator: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string type: array x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object - x-kubernetes-map-type: atomic weight: - description: Weight associated with matching - the corresponding nodeSelectorTerm, in - the range 1-100. + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. format: int32 type: integer required: - - preference + - podAffinityTerm - weight type: object type: array @@ -28861,42 +30602,49 @@ spec: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector - terms. The terms are ORed. - items: + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. properties: matchExpressions: - description: A list of node selector - requirements by node's labels. + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that - the selector applies to. + description: key is the label + key that the selector applies + to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -28907,30 +30655,77 @@ spec: type: object type: array x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector - requirements by node's fields. + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. items: description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. properties: key: - description: The label key that - the selector applies to. + description: key is the label + key that the selector applies + to. type: string operator: description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. type: string values: description: |- - An array of string values. If the operator is In or NotIn, + values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. + the values array must be empty. This array is replaced during a strategic + merge patch. items: type: string type: array @@ -28941,28 +30736,53 @@ spec: type: object type: array x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object type: object x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic type: object - podAffinity: - description: Describes pod affinity scheduling rules - (e.g. co-locate this pod in the same node, zone, - etc. as some other pod(s)). + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same node, + zone, etc. as some other pod(s)). properties: preferredDuringSchedulingIgnoredDuringExecution: description: |- The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose + the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), + request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. @@ -29134,848 +30954,1944 @@ spec: format: int32 type: integer required: - - podAffinityTerm - - weight + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey type: object type: array x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: + type: object + type: object + priorityClassName: + description: |- + Priority class name for the pgBackRest repo host pod. Changing this value + causes PostgreSQL to restart. + More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + type: string + resources: + description: Resource requirements for a pgBackRest repository + host + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + securityContext: + description: SecurityContext defines the security settings + for PGBackRest pod. + properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + fsGroup: + description: |- + A special supplemental group that applies to all containers in a pod. + Some volume types allow the Kubelet to change the ownership of that volume + to be owned by the pod: + + 1. The owning GID will be the FSGroup + 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- + + If unset, the Kubelet will not modify the ownership and permissions of any volume. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + fsGroupChangePolicy: + description: |- + fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + before being exposed inside Pod. This field will only apply to + volume types which support fsGroup based ownership(and permissions). + It will have no effect on ephemeral volume types such as: secret, configmaps + and emptydir. + Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + Note that this field cannot be set when spec.os.name is windows. + type: string + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence + for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxChangePolicy: + description: |- + seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. + It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. + Valid values are "MountOption" and "Recursive". + + "Recursive" means relabeling of all files on all Pod volumes by the container runtime. + This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. + + "MountOption" mounts all eligible Pod volumes with `-o context` mount option. + This requires all Pods that share the same volume to use the same SELinux label. + It is not possible to share the same volume among privileged and unprivileged Pods. + Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes + whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their + CSIDriver instance. Other volumes are always re-labelled recursively. + "MountOption" value is allowed only when SELinuxMount feature gate is enabled. + + If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. + If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes + and "Recursive" for all other volumes. + + This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. + + All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. + Note that this field cannot be set when spec.os.name is windows. + type: string + seLinuxOptions: + description: |- + The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in SecurityContext. If set in + both SecurityContext and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that + applies to the container. + type: string + role: + description: Role is a SELinux role label that + applies to the container. + type: string + type: + description: Type is a SELinux type label that + applies to the container. + type: string + user: + description: User is a SELinux user label that + applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + supplementalGroups: + description: |- + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and fsGroup (if specified). If + the SupplementalGroupsPolicy feature is enabled, the + supplementalGroupsPolicy field determines whether these are in addition + to or instead of any group memberships defined in the container image. + If unspecified, no additional groups are added, though group memberships + defined in the container image may still be used, depending on the + supplementalGroupsPolicy field. + Note that this field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". If not specified, "Merge" is used. + (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled + and the container runtime must implement support for this feature. + Note that this field cannot be set when spec.os.name is windows. + type: string + sysctls: + description: |- + Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + sysctls (by the container runtime) might fail to launch. + Note that this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to + be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + sidecars: + description: |- + Custom sidecars for PostgreSQL instance pods. Changing this value causes + PostgreSQL to restart. + items: + description: A single application container that you + want to run within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: + name: + default: "" description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling - rules (e.g. avoid putting this pod in the same node, - zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched - WeightedPodAffinityTerm fields are added per-node - to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, - associated with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is - a list of label selector requirements. - The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source must be a C_IDENTIFIER. All invalid keys + will be reported as an event when the container is starting. When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source + of a set of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the + name of each environment variable. Must + be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret + must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to + execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. type: string required: - - topologyKey + - port type: object - weight: + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. + exec: + description: Exec specifies a command to + execute in the container. properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET + request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in + the request. HTTP allows repeated + headers. + items: + description: HTTPHeader describes + a custom header to be used in HTTP + probes properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: + name: description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field + value type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic required: - - key - - operator + - name + - value type: object type: array x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - x-kubernetes-map-type: atomic - matchLabelKeys: + sleep: + description: Sleep represents a duration + that the container should sleep. + properties: + seconds: + description: Seconds is the number of + seconds to sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to + connect to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network + port in a single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external + port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. items: type: string type: array x-kubernetes-list-type: atomic - mismatchLabelKeys: + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. items: - type: string + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object type: array x-kubernetes-list-type: atomic - namespaceSelector: + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The - requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label - key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: Resources resize policy for the container. + items: + description: ContainerResizePolicy represents + resource resize policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one + entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This field may only be set for init containers, and the only allowed value is "Always". + For non-init containers or when this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Setting the RestartPolicy as "Always" for the init container will have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities items: + description: Capability represent POSIX + capabilities type type: string type: array x-kubernetes-list-type: atomic - topologyKey: + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label + that applies to the container. + type: string + role: + description: Role is a SELinux role label + that applies to the container. + type: string + type: + description: Type is a SELinux type label + that applies to the container. + type: string + user: + description: User is a SELinux user label + that applies to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. type: string required: - - topologyKey + - type type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - priorityClassName: - description: |- - Priority class name for the pgBackRest repo host pod. Changing this value - causes PostgreSQL to restart. - More info: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ - type: string - resources: - description: Resource requirements for a pgBackRest repository - host - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: + windowsOptions: description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the + name of the GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - securityContext: - description: SecurityContext defines the security settings - for PGBackRest pod. - properties: - appArmorProfile: - description: |- - appArmorProfile is the AppArmor options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile loaded on the node that should be used. - The profile must be preconfigured on the node to work. - Must match the loaded name of the profile. - Must be set if and only if type is "Localhost". - type: string - type: - description: |- - type indicates which kind of AppArmor profile will be applied. - Valid options are: - Localhost - a profile pre-loaded on the node. - RuntimeDefault - the container runtime's default profile. - Unconfined - no AppArmor enforcement. - type: string - required: - - type - type: object - fsGroup: - description: |- - A special supplemental group that applies to all containers in a pod. - Some volume types allow the Kubelet to change the ownership of that volume - to be owned by the pod: - - 1. The owning GID will be the FSGroup - 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) - 3. The permission bits are OR'd with rw-rw---- - - If unset, the Kubelet will not modify the ownership and permissions of any volume. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - fsGroupChangePolicy: - description: |- - fsGroupChangePolicy defines behavior of changing ownership and permission of the volume - before being exposed inside Pod. This field will only apply to - volume types which support fsGroup based ownership(and permissions). - It will have no effect on ephemeral volume types such as: secret, configmaps - and emptydir. - Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. - Note that this field cannot be set when spec.os.name is windows. - type: string - runAsGroup: - description: |- - The GID to run the entrypoint of the container process. - Uses runtime default if unset. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - runAsNonRoot: - description: |- - Indicates that the container must run as a non-root user. - If true, the Kubelet will validate the image at runtime to ensure that it - does not run as UID 0 (root) and fail to start the container if it does. - If unset or false, no such validation will be performed. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: boolean - runAsUser: - description: |- - The UID to run the entrypoint of the container process. - Defaults to user specified in image metadata if unspecified. - May also be set in SecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence - for that container. - Note that this field cannot be set when spec.os.name is windows. - format: int64 - type: integer - seLinuxChangePolicy: - description: |- - seLinuxChangePolicy defines how the container's SELinux label is applied to all volumes used by the Pod. - It has no effect on nodes that do not support SELinux or to volumes does not support SELinux. - Valid values are "MountOption" and "Recursive". - - "Recursive" means relabeling of all files on all Pod volumes by the container runtime. - This may be slow for large volumes, but allows mixing privileged and unprivileged Pods sharing the same volume on the same node. + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute + in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. + Number must be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - "MountOption" mounts all eligible Pod volumes with `-o context` mount option. - This requires all Pods that share the same volume to use the same SELinux label. - It is not possible to share the same volume among privileged and unprivileged Pods. - Eligible volumes are in-tree FibreChannel and iSCSI volumes, and all CSI volumes - whose CSI driver announces SELinux support by setting spec.seLinuxMount: true in their - CSIDriver instance. Other volumes are always re-labelled recursively. - "MountOption" value is allowed only when SELinuxMount feature gate is enabled. + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request + to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the + request. HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP + server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection + to a TCP port. + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block + devices to be used by the container. + items: + description: volumeDevice describes a mapping + of a raw block device within a container. + properties: + devicePath: + description: devicePath is the path inside + of the container that the device will be + mapped to. + type: string + name: + description: name must match the name of a + persistentVolumeClaim in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting + of a Volume within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a + Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. - If not specified and SELinuxMount feature gate is enabled, "MountOption" is used. - If not specified and SELinuxMount feature gate is disabled, "MountOption" is used for ReadWriteOncePod volumes - and "Recursive" for all other volumes. + If ReadOnly is false, this field has no meaning and must be unspecified. - This field affects only Pods that have SELinux label set, either in PodSecurityContext or in SecurityContext of all containers. + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. - All Pods that use the same volume should use the same seLinuxChangePolicy, otherwise some pods can get stuck in ContainerCreating state. - Note that this field cannot be set when spec.os.name is windows. - type: string - seLinuxOptions: - description: |- - The SELinux context to be applied to all containers. - If unspecified, the container runtime will allocate a random SELinux context for each - container. May also be set in SecurityContext. If set in - both SecurityContext and PodSecurityContext, the value specified in SecurityContext - takes precedence for that container. - Note that this field cannot be set when spec.os.name is windows. - properties: - level: - description: Level is SELinux level label that - applies to the container. - type: string - role: - description: Role is a SELinux role label that - applies to the container. - type: string - type: - description: Type is a SELinux type label that - applies to the container. - type: string - user: - description: User is a SELinux user label that - applies to the container. - type: string - type: object - seccompProfile: - description: |- - The seccomp options to use by the containers in this pod. - Note that this field cannot be set when spec.os.name is windows. - properties: - localhostProfile: - description: |- - localhostProfile indicates a profile defined in a file on the node should be used. - The profile must be preconfigured on the node to work. - Must be a descending path, relative to the kubelet's configured seccomp profile location. - Must be set if type is "Localhost". Must NOT be set for any other type. - type: string - type: - description: |- - type indicates which kind of seccomp profile will be applied. - Valid options are: + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). - Localhost - a profile defined in a file on the node should be used. - RuntimeDefault - the container runtime default profile should be used. - Unconfined - no profile should be applied. - type: string - required: - - type - type: object - supplementalGroups: - description: |- - A list of groups applied to the first process run in each container, in - addition to the container's primary GID and fsGroup (if specified). If - the SupplementalGroupsPolicy feature is enabled, the - supplementalGroupsPolicy field determines whether these are in addition - to or instead of any group memberships defined in the container image. - If unspecified, no additional groups are added, though group memberships - defined in the container image may still be used, depending on the - supplementalGroupsPolicy field. - Note that this field cannot be set when spec.os.name is windows. - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - supplementalGroupsPolicy: - description: |- - Defines how supplemental groups of the first container processes are calculated. - Valid values are "Merge" and "Strict". If not specified, "Merge" is used. - (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled - and the container runtime must implement support for this feature. - Note that this field cannot be set when spec.os.name is windows. - type: string - sysctls: - description: |- - Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported - sysctls (by the container runtime) might fail to launch. - Note that this field cannot be set when spec.os.name is windows. - items: - description: Sysctl defines a kernel parameter to - be set - properties: - name: - description: Name of a property to set - type: string - value: - description: Value of a property to set - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - description: |- - The Windows specific settings applied to all containers. - If unspecified, the options within a container's SecurityContext will be used. - If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. - Note that this field cannot be set when spec.os.name is linux. - properties: - gmsaCredentialSpec: - description: |- - GMSACredentialSpec is where the GMSA admission webhook - (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the - GMSA credential spec named by the GMSACredentialSpecName field. - type: string - gmsaCredentialSpecName: - description: GMSACredentialSpecName is the name - of the GMSA credential spec to use. - type: string - hostProcess: - description: |- - HostProcess determines if a container should be run as a 'Host Process' container. - All of a Pod's containers must have the same effective HostProcess value - (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). - In addition, if HostProcess is true then HostNetwork must also be set to true. - type: boolean - runAsUserName: - description: |- - The UserName in Windows to run the entrypoint of the container process. - Defaults to the user specified in image metadata if unspecified. - May also be set in PodSecurityContext. If set in both SecurityContext and - PodSecurityContext, the value specified in SecurityContext takes precedence. - type: string - type: object - type: object + If this field is not specified, it is treated as an equivalent of Disabled. + type: string + subPath: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + type: array sshConfigMap: description: |- ConfigMap containing custom SSH configuration. diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 76eb8d5606..79984cc796 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -730,8 +730,15 @@ func (r *Reconciler) generateRepoHostIntent(ctx context.Context, postgresCluster // K8SPG-435 resources := corev1.ResourceRequirements{} - if postgresCluster.Spec.Backups.PGBackRest.RepoHost != nil { + if repoHost := postgresCluster.Spec.Backups.PGBackRest.RepoHost; repoHost != nil { resources = postgresCluster.Spec.Backups.PGBackRest.RepoHost.Resources + + // K8SPG-832 + // If the PGBackrestRepoHostSidecars feature gate is enabled and instance sidecars are + // defined, add the defined container to the Pod. + if feature.Enabled(ctx, feature.PGBackrestRepoHostSidecars) && repoHost.Sidecars != nil { + repo.Spec.Template.Spec.Containers = append(repo.Spec.Template.Spec.Containers, repoHost.Sidecars...) + } } sizeLimit := getTMPSizeLimit(repo.Labels[naming.LabelVersion], resources) diff --git a/internal/feature/features.go b/internal/feature/features.go index ae0d4ac15b..a327dac503 100644 --- a/internal/feature/features.go +++ b/internal/feature/features.go @@ -83,6 +83,9 @@ const ( // Support custom sidecars for pgBouncer Pods PGBouncerSidecars = "PGBouncerSidecars" + // K8SPG-832: Support custom sidecars for pgbackrest repo-host Pods + PGBackrestRepoHostSidecars = "PGBackrestSidecars" + // Adjust PGUpgrade parallelism according to CPU resources PGUpgradeCPUConcurrency = "PGUpgradeCPUConcurrency" @@ -98,15 +101,16 @@ func NewGate() MutableGate { gate := featuregate.NewFeatureGate() if err := gate.Add(map[Feature]featuregate.FeatureSpec{ - AppendCustomQueries: {Default: false, PreRelease: featuregate.Alpha}, - AutoCreateUserSchema: {Default: true, PreRelease: featuregate.Beta}, - AutoGrowVolumes: {Default: false, PreRelease: featuregate.Alpha}, - BridgeIdentifiers: {Default: false, PreRelease: featuregate.Alpha}, - InstanceSidecars: {Default: false, PreRelease: featuregate.Alpha}, - PGBouncerSidecars: {Default: false, PreRelease: featuregate.Alpha}, - PGUpgradeCPUConcurrency: {Default: false, PreRelease: featuregate.Alpha}, - TablespaceVolumes: {Default: false, PreRelease: featuregate.Alpha}, - VolumeSnapshots: {Default: false, PreRelease: featuregate.Alpha}, + AppendCustomQueries: {Default: false, PreRelease: featuregate.Alpha}, + AutoCreateUserSchema: {Default: true, PreRelease: featuregate.Beta}, + AutoGrowVolumes: {Default: false, PreRelease: featuregate.Alpha}, + BridgeIdentifiers: {Default: false, PreRelease: featuregate.Alpha}, + InstanceSidecars: {Default: false, PreRelease: featuregate.Alpha}, + PGBouncerSidecars: {Default: false, PreRelease: featuregate.Alpha}, + PGBackrestRepoHostSidecars: {Default: false, PreRelease: featuregate.Alpha}, + PGUpgradeCPUConcurrency: {Default: false, PreRelease: featuregate.Alpha}, + TablespaceVolumes: {Default: false, PreRelease: featuregate.Alpha}, + VolumeSnapshots: {Default: false, PreRelease: featuregate.Alpha}, }); err != nil { panic(err) } diff --git a/internal/feature/features_test.go b/internal/feature/features_test.go index b05052a345..729fa8660a 100644 --- a/internal/feature/features_test.go +++ b/internal/feature/features_test.go @@ -22,6 +22,7 @@ func TestDefaults(t *testing.T) { assert.Assert(t, false == gate.Enabled(BridgeIdentifiers)) assert.Assert(t, false == gate.Enabled(InstanceSidecars)) assert.Assert(t, false == gate.Enabled(PGBouncerSidecars)) + assert.Assert(t, false == gate.Enabled(PGBackrestRepoHostSidecars)) assert.Assert(t, false == gate.Enabled(PGUpgradeCPUConcurrency)) assert.Assert(t, false == gate.Enabled(TablespaceVolumes)) assert.Assert(t, false == gate.Enabled(VolumeSnapshots)) diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index ef0d218b5b..6211342123 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -1059,6 +1059,288 @@ var _ = Describe("Security context", Ordered, func() { }) }) +var _ = Describe("Sidecars", Ordered, func() { + gate := feature.NewGate() + err := gate.SetFromMap(map[string]bool{ + feature.InstanceSidecars: true, + feature.PGBouncerSidecars: true, + feature.PGBackrestRepoHostSidecars: true, + }) + Expect(err).NotTo(HaveOccurred()) + + ctx := feature.NewContext(context.Background(), gate) + + const crName = "sidecars" + const ns = crName + crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName, + Namespace: ns, + }, + } + + BeforeAll(func() { + By("Creating the Namespace to perform the tests") + err := k8sClient.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the Namespace to perform the tests") + _ = k8sClient.Delete(ctx, namespace) + }) + + cr, err := readDefaultCR(crName, ns) + It("should read defautl cr.yaml", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + It("should create PerconaPGCluster", func() { + for i := range cr.Spec.InstanceSets { + i := &cr.Spec.InstanceSets[i] + i.Sidecars = []corev1.Container{ + { + Name: "instance-sidecar", + Command: []string{"instance-cmd"}, + Image: "instance-image", + }, + } + } + cr.Spec.Proxy.PGBouncer.Sidecars = []corev1.Container{ + { + Name: "pgbouncer-sidecar", + Command: []string{"pgbouncer-cmd"}, + Image: "pgbouncer-image", + }, + } + cr.Spec.Backups.PGBackRest.RepoHost.Sidecars = []corev1.Container{ + { + Name: "repohost-sidecar", + Command: []string{"repohost-cmd"}, + Image: "repohost-image", + }, + } + status := cr.Status + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + cr.Status = status + Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) + }) + + It("should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + + getContainer := func(containers []corev1.Container, name string) *corev1.Container { + for _, c := range containers { + if c.Name == name { + return &c + } + } + return nil + } + + It("Instances should have sidecar", func() { + stsList := &appsv1.StatefulSetList{} + labels := map[string]string{ + "postgres-operator.crunchydata.com/data": "postgres", + "postgres-operator.crunchydata.com/cluster": crName, + } + err = k8sClient.List(ctx, stsList, client.InNamespace(cr.Namespace), client.MatchingLabels(labels)) + Expect(err).NotTo(HaveOccurred()) + Expect(stsList.Items).NotTo(BeEmpty()) + + for _, sts := range stsList.Items { + sidecar := getContainer(sts.Spec.Template.Spec.Containers, "instance-sidecar") + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Command).To(Equal([]string{"instance-cmd"})) + Expect(sidecar.Image).To(Equal("instance-image")) + } + }) + + It("PgBouncer should have sidecar", func() { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName + "-pgbouncer", + Namespace: cr.Namespace, + }, + } + err = k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment), deployment) + Expect(err).NotTo(HaveOccurred()) + sidecar := getContainer(deployment.Spec.Template.Spec.Containers, "pgbouncer-sidecar") + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Command).To(Equal([]string{"pgbouncer-cmd"})) + Expect(sidecar.Image).To(Equal("pgbouncer-image")) + }) + + It("PgBackrest Repo should have sidecar", func() { + sts := &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName + "-repo-host", + Namespace: cr.Namespace, + }, + } + err = k8sClient.Get(ctx, client.ObjectKeyFromObject(sts), sts) + Expect(err).NotTo(HaveOccurred()) + sidecar := getContainer(sts.Spec.Template.Spec.Containers, "repohost-sidecar") + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Command).To(Equal([]string{"repohost-cmd"})) + Expect(sidecar.Image).To(Equal("repohost-image")) + }) + + It("should update PerconaPGCluster with multiple sidecars", func() { + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(cr), cr)).Should(Succeed()) + + for i := range cr.Spec.InstanceSets { + i := &cr.Spec.InstanceSets[i] + i.Sidecars = []corev1.Container{ + { + Name: "instance-sidecar-2", + Command: []string{"instance-cmd-2"}, + Image: "instance-image-2", + }, + { + Name: "instance-sidecar", + Command: []string{"instance-cmd"}, + Image: "instance-image", + }, + } + } + cr.Spec.Proxy.PGBouncer.Sidecars = []corev1.Container{ + { + Name: "pgbouncer-sidecar", + Command: []string{"pgbouncer-cmd"}, + Image: "pgbouncer-image", + }, + { + Name: "pgbouncer-sidecar-2", + Command: []string{"pgbouncer-cmd-2"}, + Image: "pgbouncer-image-2", + }, + { + Name: "pgbouncer-sidecar-3", + Command: []string{"pgbouncer-cmd-3"}, + Image: "pgbouncer-image-3", + }, + } + cr.Spec.Backups.PGBackRest.RepoHost.Sidecars = []corev1.Container{ + { + Name: "repohost-sidecar-2", + Command: []string{"repohost-cmd-2"}, + Image: "repohost-image-2", + }, + { + Name: "repohost-sidecar", + Command: []string{"repohost-cmd"}, + Image: "repohost-image", + }, + { + Name: "repohost-sidecar-3", + Command: []string{"repohost-cmd-3"}, + Image: "repohost-image-3", + }, + } + Expect(k8sClient.Update(ctx, cr)).Should(Succeed()) + }) + + It("should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + + It("Instances should have multiple sidecars", func() { + stsList := &appsv1.StatefulSetList{} + labels := map[string]string{ + "postgres-operator.crunchydata.com/data": "postgres", + "postgres-operator.crunchydata.com/cluster": crName, + } + err = k8sClient.List(ctx, stsList, client.InNamespace(cr.Namespace), client.MatchingLabels(labels)) + Expect(err).NotTo(HaveOccurred()) + Expect(stsList.Items).NotTo(BeEmpty()) + + for _, sts := range stsList.Items { + l := len(sts.Spec.Template.Spec.Containers) + sidecar := sts.Spec.Template.Spec.Containers[l-4] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("instance-sidecar-2")) + Expect(sidecar.Command).To(Equal([]string{"instance-cmd-2"})) + Expect(sidecar.Image).To(Equal("instance-image-2")) + + sidecar = sts.Spec.Template.Spec.Containers[l-3] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("instance-sidecar")) + Expect(sidecar.Command).To(Equal([]string{"instance-cmd"})) + Expect(sidecar.Image).To(Equal("instance-image")) + } + }) + + It("PgBouncer should have multiple sidecars", func() { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName + "-pgbouncer", + Namespace: cr.Namespace, + }, + } + err = k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment), deployment) + Expect(err).NotTo(HaveOccurred()) + + l := len(deployment.Spec.Template.Spec.Containers) + sidecar := deployment.Spec.Template.Spec.Containers[l-3] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("pgbouncer-sidecar")) + Expect(sidecar.Command).To(Equal([]string{"pgbouncer-cmd"})) + Expect(sidecar.Image).To(Equal("pgbouncer-image")) + + sidecar = deployment.Spec.Template.Spec.Containers[l-2] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("pgbouncer-sidecar-2")) + Expect(sidecar.Command).To(Equal([]string{"pgbouncer-cmd-2"})) + Expect(sidecar.Image).To(Equal("pgbouncer-image-2")) + + sidecar = deployment.Spec.Template.Spec.Containers[l-1] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("pgbouncer-sidecar-3")) + Expect(sidecar.Command).To(Equal([]string{"pgbouncer-cmd-3"})) + Expect(sidecar.Image).To(Equal("pgbouncer-image-3")) + }) + + It("PgBackrest Repo should have multiple sidecars", func() { + sts := &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName + "-repo-host", + Namespace: cr.Namespace, + }, + } + err = k8sClient.Get(ctx, client.ObjectKeyFromObject(sts), sts) + Expect(err).NotTo(HaveOccurred()) + + l := len(sts.Spec.Template.Spec.Containers) + sidecar := sts.Spec.Template.Spec.Containers[l-3] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("repohost-sidecar-2")) + Expect(sidecar.Command).To(Equal([]string{"repohost-cmd-2"})) + Expect(sidecar.Image).To(Equal("repohost-image-2")) + + sidecar = sts.Spec.Template.Spec.Containers[l-2] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("repohost-sidecar")) + Expect(sidecar.Command).To(Equal([]string{"repohost-cmd"})) + Expect(sidecar.Image).To(Equal("repohost-image")) + + sidecar = sts.Spec.Template.Spec.Containers[l-1] + Expect(sidecar).NotTo(BeNil()) + Expect(sidecar.Name).To(Equal("repohost-sidecar-3")) + Expect(sidecar.Command).To(Equal([]string{"repohost-cmd-3"})) + Expect(sidecar.Image).To(Equal("repohost-image-3")) + }) +}) + var _ = Describe("Operator-created sidecar container resources", Ordered, func() { ctx := context.Background() diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go index e931bc8b11..a824924260 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go @@ -255,6 +255,11 @@ type PGBackRestRepoHost struct { // SecurityContext defines the security settings for PGBackRest pod. // +optional SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` + + // Custom sidecars for PostgreSQL instance pods. Changing this value causes + // PostgreSQL to restart. + // +optional + Sidecars []corev1.Container `json:"sidecars,omitempty"` } // PGBackRestRestore defines an in-place restore for the PostgresCluster. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 99765c4df8..fc1592e39b 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -1091,6 +1091,13 @@ func (in *PGBackRestRepoHost) DeepCopyInto(out *PGBackRestRepoHost) { *out = new(corev1.PodSecurityContext) (*in).DeepCopyInto(*out) } + if in.Sidecars != nil { + in, out := &in.Sidecars, &out.Sidecars + *out = make([]corev1.Container, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PGBackRestRepoHost. From 282ccc6fb2e4e4c7485d5ac726aa8d8f20e13288 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 20:20:54 +0300 Subject: [PATCH 119/300] CLOUD-727: Bump aquasecurity/trivy-action from 0.31.0 to 0.32.0 (#1239) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.31.0 to 0.32.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.31.0...0.32.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-version: 0.32.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scan.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index da69cf2c11..a776fdfb11 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -31,7 +31,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/arm64) - uses: aquasecurity/trivy-action@0.31.0 + uses: aquasecurity/trivy-action@0.32.0 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64' format: 'table' @@ -50,7 +50,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/amd64) - uses: aquasecurity/trivy-action@0.31.0 + uses: aquasecurity/trivy-action@0.32.0 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64' format: 'table' From 7745c60c59752048e89ee1d08e494a7a91f8317f Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Tue, 5 Aug 2025 12:27:52 +0300 Subject: [PATCH 120/300] K8SPG-833: add `env` and `envFrom` fields (#1231) * K8SPG-833: add `env` and `envFrom` fields https://perconadev.atlassian.net/browse/K8SPG-833 * fix misprint * address comment * add envFrom hashes * fix lint * revert formatting --------- Co-authored-by: Viacheslav Sarzhan --- ...ator.crunchydata.com_postgresclusters.yaml | 503 +++++++++ .../pgv2.percona.com_perconapgclusters.yaml | 499 ++++++++ .../pgv2.percona.com_perconapgclusters.yaml | 499 ++++++++ ...ator.crunchydata.com_postgresclusters.yaml | 503 +++++++++ deploy/bundle.yaml | 1002 +++++++++++++++++ deploy/cr.yaml | 18 + deploy/crd.yaml | 1002 +++++++++++++++++ deploy/cw-bundle.yaml | 1002 +++++++++++++++++ .../controller/postgrescluster/instance.go | 12 + .../controller/postgrescluster/pgbackrest.go | 24 + internal/pgbouncer/reconcile.go | 12 + percona/controller/pgcluster/controller.go | 49 + .../controller/pgcluster/controller_test.go | 225 ++++ percona/controller/pgcluster/secret.go | 45 + percona/naming/annotations.go | 4 + .../v2/perconapgcluster_types.go | 18 +- .../v2/zz_generated.deepcopy.go | 42 + .../v1beta1/pgbackrest_types.go | 5 + .../v1beta1/pgbouncer_types.go | 5 + .../v1beta1/postgrescluster_types.go | 5 + .../v1beta1/zz_generated.deepcopy.go | 42 + 21 files changed, 5515 insertions(+), 1 deletion(-) create mode 100644 percona/controller/pgcluster/secret.go diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 38af5d821e..0f458588d8 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -374,6 +374,174 @@ spec: type: object type: object type: array + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -12917,6 +13085,173 @@ spec: PersistentVolume backing this claim. type: string type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -19135,6 +19470,174 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array exposeSuperusers: description: Allow SUPERUSERs to connect through PGBouncer. type: boolean diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 1b4d25e1c1..ff79e1f5ab 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -532,6 +532,174 @@ spec: type: object type: object type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -11370,6 +11538,171 @@ spec: PersistentVolume backing this claim. type: string type: object + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -17403,6 +17736,172 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array expose: description: Specification of the service that exposes PgBouncer. properties: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index e23c7b664c..8f6b7eb916 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -939,6 +939,174 @@ spec: type: object type: object type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -11777,6 +11945,171 @@ spec: PersistentVolume backing this claim. type: string type: object + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -17810,6 +18143,172 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array expose: description: Specification of the service that exposes PgBouncer. properties: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index d0d6f12e43..2b15ddaeaa 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -366,6 +366,174 @@ spec: type: object type: object type: array + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -12859,6 +13027,173 @@ spec: - accessModes - resources type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -19044,6 +19379,174 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array exposeSuperusers: description: Allow SUPERUSERs to connect through PGBouncer. type: boolean diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index cbb781127d..9d26c605c0 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -1236,6 +1236,174 @@ spec: type: object type: object type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -12074,6 +12242,171 @@ spec: PersistentVolume backing this claim. type: string type: object + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -18107,6 +18440,172 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array expose: description: Specification of the service that exposes PgBouncer. properties: @@ -28586,6 +29085,174 @@ spec: type: object type: object type: array + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -41079,6 +41746,173 @@ spec: - accessModes - resources type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -47264,6 +48098,174 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array exposeSuperusers: description: Allow SUPERUSERs to connect through PGBouncer. type: boolean diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 5e494820b4..ac61fd2788 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -181,6 +181,12 @@ spec: instances: - name: instance1 replicas: 3 +# env: +# - name: MY_ENV +# value: "1000" +# envFrom: +# - secretRef: +# name: instance-env-secret # initContainer: # image: docker.io/perconalab/percona-postgresql-operator:main # resources: @@ -307,6 +313,12 @@ spec: pgBouncer: replicas: 3 image: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 +# env: +# - name: MY_ENV +# value: "1000" +# envFrom: +# - secretRef: +# name: pgbouncer-env-secret # exposeSuperusers: true # resources: # limits: @@ -398,6 +410,12 @@ spec: # metadata: # labels: image: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 +# env: +# - name: MY_ENV +# value: "1000" +# envFrom: +# - secretRef: +# name: repo-host-env-secret # initContainer: # image: docker.io/perconalab/percona-postgresql-operator:main # resources: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 52632fe0df..556c385de9 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -1236,6 +1236,174 @@ spec: type: object type: object type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -12074,6 +12242,171 @@ spec: PersistentVolume backing this claim. type: string type: object + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -18107,6 +18440,172 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array expose: description: Specification of the service that exposes PgBouncer. properties: @@ -28586,6 +29085,174 @@ spec: type: object type: object type: array + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -41079,6 +41746,173 @@ spec: - accessModes - resources type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -47264,6 +48098,174 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array exposeSuperusers: description: Allow SUPERUSERs to connect through PGBouncer. type: boolean diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index a7f1f1c494..9553c74d7a 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -1236,6 +1236,174 @@ spec: type: object type: object type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -12074,6 +12242,171 @@ spec: PersistentVolume backing this claim. type: string type: object + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -18107,6 +18440,172 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array expose: description: Specification of the service that exposes PgBouncer. properties: @@ -28586,6 +29085,174 @@ spec: type: object type: object type: array + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array global: additionalProperties: type: string @@ -41079,6 +41746,173 @@ spec: - accessModes - resources type: object + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of each + environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array initContainer: description: |- K8SPG-708 @@ -47264,6 +48098,174 @@ spec: type: boolean type: object x-kubernetes-map-type: atomic + env: + description: K8SPG-833 + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + envFrom: + description: K8SPG-833 + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: Optional text to prepend to the name of + each environment variable. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array exposeSuperusers: description: Allow SUPERUSERs to connect through PGBouncer. type: boolean diff --git a/internal/controller/postgrescluster/instance.go b/internal/controller/postgrescluster/instance.go index 079b1d2e4f..eab8d75cb6 100644 --- a/internal/controller/postgrescluster/instance.go +++ b/internal/controller/postgrescluster/instance.go @@ -1243,6 +1243,18 @@ func (r *Reconciler) reconcileInstance( addDevSHM(&instance.Spec.Template) } + // K8SPG-833 + if cluster.CompareVersion("2.8.0") >= 0 { + for i := range instance.Spec.Template.Spec.Containers { + if len(spec.Env) != 0 { + instance.Spec.Template.Spec.Containers[i].Env = append(instance.Spec.Template.Spec.Containers[i].Env, spec.Env...) + } + if len(spec.EnvFrom) != 0 { + instance.Spec.Template.Spec.Containers[i].EnvFrom = append(instance.Spec.Template.Spec.Containers[i].EnvFrom, spec.EnvFrom...) + } + } + } + if err == nil { err = errors.WithStack(r.apply(ctx, instance)) } diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 79984cc796..4144318f9c 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -744,6 +744,18 @@ func (r *Reconciler) generateRepoHostIntent(ctx context.Context, postgresCluster addTMPEmptyDir(&repo.Spec.Template, sizeLimit) + // K8SPG-833 + if pgbackrest := postgresCluster.Spec.Backups.PGBackRest; postgresCluster.CompareVersion("2.8.0") >= 0 { + for i := range repo.Spec.Template.Spec.Containers { + if len(pgbackrest.Env) != 0 { + repo.Spec.Template.Spec.Containers[i].Env = append(repo.Spec.Template.Spec.Containers[i].Env, pgbackrest.Env...) + } + if len(pgbackrest.EnvFrom) != 0 { + repo.Spec.Template.Spec.Containers[i].EnvFrom = append(repo.Spec.Template.Spec.Containers[i].EnvFrom, pgbackrest.EnvFrom...) + } + } + } + // set ownership references if err := r.setControllerReference(postgresCluster, repo); err != nil { return nil, err @@ -931,6 +943,18 @@ func generateBackupJobSpecIntent(ctx context.Context, postgresCluster *v1beta1.P if postgresCluster.Spec.Backups.PGBackRest.Jobs.BackoffLimit != nil { jobSpec.BackoffLimit = postgresCluster.Spec.Backups.PGBackRest.Jobs.BackoffLimit } + + // K8SPG-833 + if postgresCluster.CompareVersion("2.8.0") >= 0 { + for i := range jobSpec.Template.Spec.Containers { + if len(postgresCluster.Spec.Backups.PGBackRest.Env) != 0 { + jobSpec.Template.Spec.Containers[i].Env = append(jobSpec.Template.Spec.Containers[i].Env, postgresCluster.Spec.Backups.PGBackRest.Env...) + } + if len(postgresCluster.Spec.Backups.PGBackRest.EnvFrom) != 0 { + jobSpec.Template.Spec.Containers[i].EnvFrom = append(jobSpec.Template.Spec.Containers[i].EnvFrom, postgresCluster.Spec.Backups.PGBackRest.EnvFrom...) + } + } + } } // Set the image pull secrets, if any exist. diff --git a/internal/pgbouncer/reconcile.go b/internal/pgbouncer/reconcile.go index 25d5bca9d0..9505949af5 100644 --- a/internal/pgbouncer/reconcile.go +++ b/internal/pgbouncer/reconcile.go @@ -187,6 +187,18 @@ func Pod( } outPod.Volumes = []corev1.Volume{configVolume} + + // K8SPG-833 + if pgbouncer := inCluster.Spec.Proxy.PGBouncer; inCluster.CompareVersion("2.8.0") >= 0 && pgbouncer != nil { + for i := range outPod.Containers { + if len(pgbouncer.Env) != 0 { + outPod.Containers[i].Env = append(outPod.Containers[i].Env, pgbouncer.Env...) + } + if len(pgbouncer.EnvFrom) != 0 { + outPod.Containers[i].EnvFrom = append(outPod.Containers[i].EnvFrom, pgbouncer.EnvFrom...) + } + } + } } // PostgreSQL populates outHBAs with any records needed to run PgBouncer. diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 36909b97e8..c9b8f7ba0c 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -281,6 +281,10 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "failed to handle monitor user password change") } + if err := r.handleEnvFromSecrets(ctx, cr); err != nil { + return reconcile.Result{}, errors.Wrap(err, "failed to handle envFrom secrets") + } + if err := r.reconcileCustomExtensions(ctx, cr); err != nil { return reconcile.Result{}, errors.Wrap(err, "reconcile custom extensions") } @@ -717,6 +721,51 @@ func (r *PGClusterReconciler) reconcilePMM(ctx context.Context, cr *v2.PerconaPG return nil } +func (r *PGClusterReconciler) handleEnvFromSecrets(ctx context.Context, cr *v2.PerconaPGCluster) error { + m := make(map[*[]corev1.EnvFromSource]*v1beta1.Metadata) + + for i := 0; i < len(cr.Spec.InstanceSets); i++ { + set := &cr.Spec.InstanceSets[i] + if len(set.EnvFrom) == 0 { + continue + } + if set.Metadata == nil { + set.Metadata = new(v1beta1.Metadata) + } + m[&set.EnvFrom] = set.Metadata + } + + if len(cr.Spec.Proxy.PGBouncer.EnvFrom) > 0 { + if cr.Spec.Proxy.PGBouncer.Metadata == nil { + cr.Spec.Proxy.PGBouncer.Metadata = new(v1beta1.Metadata) + } + m[&cr.Spec.Proxy.PGBouncer.EnvFrom] = cr.Spec.Proxy.PGBouncer.Metadata + } + + if len(cr.Spec.Backups.PGBackRest.EnvFrom) > 0 { + if cr.Spec.Backups.PGBackRest.Metadata == nil { + cr.Spec.Proxy.PGBouncer.Metadata = new(v1beta1.Metadata) + } + m[&cr.Spec.Backups.PGBackRest.EnvFrom] = cr.Spec.Backups.PGBackRest.Metadata + } + + for envFrom, metadata := range m { + secrets, err := getEnvFromSecrets(ctx, r.Client, cr, *envFrom) + if err != nil { + return errors.Wrap(err, "get env from secrets") + } + + if metadata.Annotations == nil { + metadata.Annotations = make(map[string]string) + } + + // If the currentHash is the same is the on the STS, restart will not happen + metadata.Annotations[pNaming.AnnotationEnvVarsSecretHash] = getSecretHash(secrets...) + } + + return nil +} + func (r *PGClusterReconciler) handleMonitorUserPassChange(ctx context.Context, cr *v2.PerconaPGCluster) error { if !cr.PMMEnabled() { return nil diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 6211342123..3f5bba0ade 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -1059,6 +1059,231 @@ var _ = Describe("Security context", Ordered, func() { }) }) +var _ = Describe("Envs", Ordered, func() { + ctx := context.Background() + + const crName = "envs" + const ns = crName + crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName, + Namespace: ns, + }, + } + + BeforeAll(func() { + By("Creating the Namespace to perform the tests") + err := k8sClient.Create(ctx, namespace) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the Namespace to perform the tests") + _ = k8sClient.Delete(ctx, namespace) + }) + + cr, err := readDefaultCR(crName, ns) + It("should read defautl cr.yaml", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + instanceEnv := []corev1.EnvVar{ + { + Name: "INSTANCE_ENV", + Value: "VALUE1", + }, + } + instanceEnvFrom := []corev1.EnvFromSource{ + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "secret-instance-env", + }, + }, + }, + } + instanceSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret-instance-env", + Namespace: ns, + }, + StringData: map[string]string{ + "instance": "test", + }, + } + + pgbouncerEnv := []corev1.EnvVar{ + { + Name: "PGBOUNCER_ENV", + Value: "VALUE2", + }, + } + pgbouncerEnvFrom := []corev1.EnvFromSource{ + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "secret-pgbouncer-env", + }, + }, + }, + } + pgbouncerSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret-pgbouncer-env", + Namespace: ns, + }, + StringData: map[string]string{ + "pgbouncer": "test", + }, + } + + repoHostEnv := []corev1.EnvVar{ + { + Name: "REPOHOST_ENV", + Value: "VALUE3", + }, + } + repoHostEnvFrom := []corev1.EnvFromSource{ + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "secret-pgbackrest-env", + }, + }, + }, + } + repoHostSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret-pgbackrest-env", + Namespace: ns, + }, + StringData: map[string]string{ + "pgbackrest": "test", + }, + } + + It("should create PerconaPGCluster", func() { + for i := range cr.Spec.InstanceSets { + cr.Spec.InstanceSets[i].Env = []corev1.EnvVar{ + { + Name: "INSTANCE_ENV", + Value: "VALUE1", + }, + } + + cr.Spec.InstanceSets[i].EnvFrom = []corev1.EnvFromSource{ + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "secret-instance-env", + }, + }, + }, + } + } + cr.Spec.Proxy.PGBouncer.Env = []corev1.EnvVar{ + { + Name: "PGBOUNCER_ENV", + Value: "VALUE2", + }, + } + cr.Spec.Proxy.PGBouncer.EnvFrom = []corev1.EnvFromSource{ + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "secret-pgbouncer-env", + }, + }, + }, + } + cr.Spec.Backups.PGBackRest.Env = []corev1.EnvVar{ + { + Name: "REPOHOST_ENV", + Value: "VALUE3", + }, + } + cr.Spec.Backups.PGBackRest.EnvFrom = []corev1.EnvFromSource{ + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "secret-pgbackrest-env", + }, + }, + }, + } + cr.Spec.CRVersion = "2.8.0" + + status := cr.Status + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + cr.Status = status + Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) + + Expect(k8sClient.Create(ctx, instanceSecret)).Should(Succeed()) + Expect(k8sClient.Create(ctx, pgbouncerSecret)).Should(Succeed()) + Expect(k8sClient.Create(ctx, repoHostSecret)).Should(Succeed()) + }) + + It("should reconcile", func() { + _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + _, err = crunchyReconciler().Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) + Expect(err).NotTo(HaveOccurred()) + }) + + It("Instances should have envs", func() { + stsList := &appsv1.StatefulSetList{} + labels := map[string]string{ + "postgres-operator.crunchydata.com/data": "postgres", + "postgres-operator.crunchydata.com/cluster": crName, + } + err = k8sClient.List(ctx, stsList, client.InNamespace(cr.Namespace), client.MatchingLabels(labels)) + Expect(err).NotTo(HaveOccurred()) + Expect(stsList.Items).NotTo(BeEmpty()) + + for _, sts := range stsList.Items { + Expect(sts.Spec.Template.Annotations[pNaming.AnnotationEnvVarsSecretHash]).To(Equal("fadefc4ed7b5e5948dc8b03f2a3a71be")) + for _, c := range sts.Spec.Template.Spec.Containers { + Expect(c.Env).To(ContainElement(instanceEnv[0])) + Expect(c.EnvFrom).To(Equal(instanceEnvFrom)) + } + } + }) + + It("PgBouncer should have envs", func() { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName + "-pgbouncer", + Namespace: cr.Namespace, + }, + } + err = k8sClient.Get(ctx, client.ObjectKeyFromObject(deployment), deployment) + Expect(err).NotTo(HaveOccurred()) + Expect(deployment.Spec.Template.Annotations[pNaming.AnnotationEnvVarsSecretHash]).To(Equal("6bc7e8df0909c789be90c630c9edce14")) + for _, c := range deployment.Spec.Template.Spec.Containers { + Expect(c.Env).To(ContainElement(pgbouncerEnv[0])) + Expect(c.EnvFrom).To(Equal(pgbouncerEnvFrom)) + } + }) + + It("PgBackrest Repo should have envs", func() { + sts := &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName + "-repo-host", + Namespace: cr.Namespace, + }, + } + err = k8sClient.Get(ctx, client.ObjectKeyFromObject(sts), sts) + Expect(err).NotTo(HaveOccurred()) + Expect(sts.Spec.Template.Annotations[pNaming.AnnotationEnvVarsSecretHash]).To(Equal("22eb2683af3f48813c0cd53f905b67d0")) + for _, c := range sts.Spec.Template.Spec.Containers { + Expect(c.Env).To(ContainElement(repoHostEnv[0])) + Expect(c.EnvFrom).To(Equal(repoHostEnvFrom)) + } + }) +}) + var _ = Describe("Sidecars", Ordered, func() { gate := feature.NewGate() err := gate.SetFromMap(map[string]bool{ diff --git a/percona/controller/pgcluster/secret.go b/percona/controller/pgcluster/secret.go new file mode 100644 index 0000000000..84c2cf9ec8 --- /dev/null +++ b/percona/controller/pgcluster/secret.go @@ -0,0 +1,45 @@ +package pgcluster + +import ( + "context" + "crypto/md5" //nolint:gosec + "fmt" + + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/percona/percona-postgresql-operator/internal/logging" + v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" +) + +func getEnvFromSecrets(ctx context.Context, cl client.Client, cr *v2.PerconaPGCluster, envFromSource []corev1.EnvFromSource) ([]corev1.Secret, error) { + log := logging.FromContext(ctx) + var secrets []corev1.Secret + for _, source := range envFromSource { + var secret corev1.Secret + if err := cl.Get(ctx, types.NamespacedName{ + Name: source.SecretRef.Name, + Namespace: cr.Namespace, + }, &secret); err != nil { + if k8serrors.IsNotFound(err) { + log.V(1).Info(fmt.Sprintf("Secret %s not found", secret.Name)) + continue + } + return nil, err + } + secrets = append(secrets, secret) + } + return secrets, nil +} + +func getSecretHash(secrets ...corev1.Secret) string { + var data string + + for _, secret := range secrets { + data += fmt.Sprintln(secret.Data) + } + + return fmt.Sprintf("%x", md5.Sum([]byte(data))) //nolint:gosec +} diff --git a/percona/naming/annotations.go b/percona/naming/annotations.go index 79a979bcfe..dadb4242c8 100644 --- a/percona/naming/annotations.go +++ b/percona/naming/annotations.go @@ -30,6 +30,10 @@ const ( // rollout restart PG pods in case monitor user password is changed. AnnotationMonitorUserSecretHash = PrefixPerconaPGV2 + "monitor-user-secret-hash" + // AnnotationEnvVarsSecretHash is the annotation that is added to + // rollout restart pods in case envFrom secret is changed. + AnnotationEnvVarsSecretHash = PrefixPerconaPGV2 + "env-secret-config-hash" + // AnnotationBackupInProgress is the annotation that is added to PerconaPGCluster to // indicate that backup is in progress. AnnotationBackupInProgress = PrefixPerconaPGV2 + "backup-in-progress" diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 858dccf5f8..412c83d61e 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -467,7 +467,6 @@ type PerconaPGClusterStatus struct { } type Patroni struct { - // +optional Status *crunchyv1beta1.PatroniStatus `json:"status,omitempty"` @@ -518,6 +517,8 @@ func (b Backups) ToCrunchy(version string) crunchyv1beta1.Backups { Restore: b.PGBackRest.Restore, InitContainer: b.PGBackRest.InitContainer, Sidecars: sc, + Env: b.PGBackRest.Env, + EnvFrom: b.PGBackRest.EnvFrom, }, } } @@ -580,6 +581,11 @@ type PGBackRestArchive struct { // Configuration for pgBackRest sidecar containers // +optional Containers *crunchyv1beta1.PGBackRestSidecars `json:"containers,omitempty"` + + // K8SPG-833 + Env []corev1.EnvVar `json:"env,omitempty"` + // K8SPG-833 + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` } type PMMQuerySource string @@ -821,6 +827,9 @@ type PGInstanceSetSpec struct { // InitContainer defines the init container for the instance container of a PostgreSQL pod. // +optional InitContainer *crunchyv1beta1.InitContainerSpec `json:"initContainer,omitempty"` + + Env []corev1.EnvVar `json:"env,omitempty"` + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` } func (p PGInstanceSetSpec) ToCrunchy() crunchyv1beta1.PostgresInstanceSetSpec { @@ -843,6 +852,8 @@ func (p PGInstanceSetSpec) ToCrunchy() crunchyv1beta1.PostgresInstanceSetSpec { SecurityContext: p.SecurityContext, TablespaceVolumes: p.TablespaceVolumes, InitContainer: p.InitContainer, + Env: p.Env, + EnvFrom: p.EnvFrom, } } @@ -1009,6 +1020,9 @@ type PGBouncerSpec struct { // SecurityContext defines the security settings for PGBouncer pods. // +optional SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` + + Env []corev1.EnvVar `json:"env,omitempty"` + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` } func (p *PGBouncerSpec) ToCrunchy(version string) *crunchyv1beta1.PGBouncerPodSpec { @@ -1034,6 +1048,8 @@ func (p *PGBouncerSpec) ToCrunchy(version string) *crunchyv1beta1.PGBouncerPodSp Tolerations: p.Tolerations, TopologySpreadConstraints: p.TopologySpreadConstraints, SecurityContext: p.SecurityContext, + Env: p.Env, + EnvFrom: p.EnvFrom, } spec.Default() diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index c6d5701cee..bfbf0041c2 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -203,6 +203,20 @@ func (in *PGBackRestArchive) DeepCopyInto(out *PGBackRestArchive) { *out = new(v1beta1.PGBackRestSidecars) (*in).DeepCopyInto(*out) } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]v1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PGBackRestArchive. @@ -291,6 +305,20 @@ func (in *PGBouncerSpec) DeepCopyInto(out *PGBouncerSpec) { *out = new(v1.PodSecurityContext) (*in).DeepCopyInto(*out) } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]v1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PGBouncerSpec. @@ -410,6 +438,20 @@ func (in *PGInstanceSetSpec) DeepCopyInto(out *PGInstanceSetSpec) { *out = new(v1beta1.InitContainerSpec) (*in).DeepCopyInto(*out) } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]v1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PGInstanceSetSpec. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go index a824924260..91a2b220f9 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go @@ -137,6 +137,11 @@ type PGBackRestArchive struct { // +optional InitContainer *InitContainerSpec `json:"initContainer,omitempty"` // K8SPG-613 + + // K8SPG-833 + Env []corev1.EnvVar `json:"env,omitempty"` + // K8SPG-833 + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` } // K8SPG-613 diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbouncer_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbouncer_types.go index 9119cd6fe3..12956a63eb 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbouncer_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbouncer_types.go @@ -139,6 +139,11 @@ type PGBouncerPodSpec struct { // SecurityContext defines the security settings for PGBouncer pods. // +optional SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` + + // K8SPG-833 + Env []corev1.EnvVar `json:"env,omitempty"` + // K8SPG-833 + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` } // PGBouncerSidecars defines the configuration for pgBouncer sidecar containers diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index b9551cecb0..1fd3fd8d8a 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -556,6 +556,11 @@ type PostgresInstanceSetSpec struct { // InitContainer defines the init container for the instance container of a PostgreSQL pod. // +optional InitContainer *InitContainerSpec `json:"initContainer,omitempty"` + + // K8SPG-833 + Env []corev1.EnvVar `json:"env,omitempty"` + // K8SPG-833 + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` } // K8SPG-708 diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index fc1592e39b..523d8dc6d7 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -870,6 +870,20 @@ func (in *PGBackRestArchive) DeepCopyInto(out *PGBackRestArchive) { *out = new(InitContainerSpec) (*in).DeepCopyInto(*out) } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]corev1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PGBackRestArchive. @@ -1344,6 +1358,20 @@ func (in *PGBouncerPodSpec) DeepCopyInto(out *PGBouncerPodSpec) { *out = new(corev1.PodSecurityContext) (*in).DeepCopyInto(*out) } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]corev1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PGBouncerPodSpec. @@ -2040,6 +2068,20 @@ func (in *PostgresInstanceSetSpec) DeepCopyInto(out *PostgresInstanceSetSpec) { *out = new(InitContainerSpec) (*in).DeepCopyInto(*out) } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]corev1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgresInstanceSetSpec. From 356833fc8dffaa6f2aaf9e11e63ed102390b356a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 21:53:08 +0300 Subject: [PATCH 121/300] CLOUD-727: Bump k8s.io/client-go from 0.33.2 to 0.33.3 (#1243) Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.33.2 to 0.33.3. - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.33.2...v0.33.3) --- updated-dependencies: - dependency-name: k8s.io/client-go dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index a95b5c268e..6fcb7a5303 100644 --- a/go.mod +++ b/go.mod @@ -34,9 +34,9 @@ require ( golang.org/x/crypto v0.40.0 google.golang.org/grpc v1.73.0 gotest.tools/v3 v3.5.2 - k8s.io/api v0.33.2 - k8s.io/apimachinery v0.33.2 - k8s.io/client-go v0.33.2 + k8s.io/api v0.33.3 + k8s.io/apimachinery v0.33.3 + k8s.io/client-go v0.33.3 k8s.io/component-base v0.33.2 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.5.0 diff --git a/go.sum b/go.sum index 509d8047d6..30c3dab9d5 100644 --- a/go.sum +++ b/go.sum @@ -336,14 +336,14 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -k8s.io/api v0.33.2 h1:YgwIS5jKfA+BZg//OQhkJNIfie/kmRsO0BmNaVSimvY= -k8s.io/api v0.33.2/go.mod h1:fhrbphQJSM2cXzCWgqU29xLDuks4mu7ti9vveEnpSXs= +k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= +k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8= k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8= -k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY= -k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.2 h1:z8CIcc0P581x/J1ZYf4CNzRKxRvQAwoAolYPbtQes+E= -k8s.io/client-go v0.33.2/go.mod h1:9mCgT4wROvL948w6f6ArJNb7yQd7QsvqavDeZHvNmHo= +k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= +k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= +k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0= k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= From cafc668c075143c595ec31b58871965c9e2e8201 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:09:31 +0300 Subject: [PATCH 122/300] CLOUD-727: Bump sigs.k8s.io/yaml from 1.5.0 to 1.6.0 (#1242) * CLOUD-727: Bump sigs.k8s.io/yaml from 1.5.0 to 1.6.0 Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.5.0 to 1.6.0. - [Release notes](https://github.com/kubernetes-sigs/yaml/releases) - [Changelog](https://github.com/kubernetes-sigs/yaml/blob/master/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/yaml/compare/v1.5.0...v1.6.0) --- updated-dependencies: - dependency-name: sigs.k8s.io/yaml dependency-version: 1.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * use hetzner worker * add make * add docker-init * remove docker-ce --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- Jenkinsfile | 12 ++++++------ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8ddb00a476..4bc55e5862 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -308,7 +308,7 @@ gpgcheck=1 repo_gpgcheck=0 gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF - sudo yum install -y google-cloud-cli google-cloud-cli-gke-gcloud-auth-plugin + sudo yum install -y make google-cloud-cli google-cloud-cli-gke-gcloud-auth-plugin """ } @@ -402,7 +402,7 @@ pipeline { AUTHOR_NAME = sh(script: "echo ${CHANGE_AUTHOR_EMAIL} | awk -F'@' '{print \$1}'", , returnStdout: true).trim() } agent { - label 'docker' + label 'docker-x64-min' } options { disableConcurrentBuilds(abortPrevious: true) @@ -522,7 +522,7 @@ pipeline { parallel { stage('cluster1') { agent { - label 'docker' + label 'docker-x64-min' } steps { prepareNode() @@ -532,7 +532,7 @@ pipeline { } stage('cluster2') { agent { - label 'docker' + label 'docker-x64-min' } steps { prepareNode() @@ -542,7 +542,7 @@ pipeline { } stage('cluster3') { agent { - label 'docker' + label 'docker-x64-min' } steps { prepareNode() @@ -552,7 +552,7 @@ pipeline { } stage('cluster4') { agent { - label 'docker' + label 'docker-x64-min' } steps { prepareNode() diff --git a/go.mod b/go.mod index 6fcb7a5303..a706e12fa5 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( k8s.io/client-go v0.33.3 k8s.io/component-base v0.33.2 sigs.k8s.io/controller-runtime v0.21.0 - sigs.k8s.io/yaml v1.5.0 + sigs.k8s.io/yaml v1.6.0 ) require ( diff --git a/go.sum b/go.sum index 30c3dab9d5..92adba28ba 100644 --- a/go.sum +++ b/go.sum @@ -362,5 +362,5 @@ sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxO sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= -sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= -sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= From 3fc048e7cb50eefe7d2b15aeb3c23f69390ffe3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:12:35 +0300 Subject: [PATCH 123/300] CLOUD-727: Bump k8s.io/component-base from 0.33.2 to 0.33.3 (#1245) Bumps [k8s.io/component-base](https://github.com/kubernetes/component-base) from 0.33.2 to 0.33.3. - [Commits](https://github.com/kubernetes/component-base/compare/v0.33.2...v0.33.3) --- updated-dependencies: - dependency-name: k8s.io/component-base dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a706e12fa5..c5eaebd23b 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( k8s.io/api v0.33.3 k8s.io/apimachinery v0.33.3 k8s.io/client-go v0.33.3 - k8s.io/component-base v0.33.2 + k8s.io/component-base v0.33.3 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.6.0 ) diff --git a/go.sum b/go.sum index 92adba28ba..6176596f32 100644 --- a/go.sum +++ b/go.sum @@ -344,8 +344,8 @@ k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= -k8s.io/component-base v0.33.2 h1:sCCsn9s/dG3ZrQTX/Us0/Sx2R0G5kwa0wbZFYoVp/+0= -k8s.io/component-base v0.33.2/go.mod h1:/41uw9wKzuelhN+u+/C59ixxf4tYQKW7p32ddkYNe2k= +k8s.io/component-base v0.33.3 h1:mlAuyJqyPlKZM7FyaoM/LcunZaaY353RXiOd2+B5tGA= +k8s.io/component-base v0.33.3/go.mod h1:ktBVsBzkI3imDuxYXmVxZ2zxJnYTZ4HAsVj9iF09qp4= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= From 733d605afc096ce512eda88d0f6a6d56c75f0c98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:14:29 +0300 Subject: [PATCH 124/300] CLOUD-727: Bump github.com/golang-jwt/jwt/v5 from 5.2.2 to 5.3.0 (#1249) Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.2 to 5.3.0. - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md) - [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.2...v5.3.0) --- updated-dependencies: - dependency-name: github.com/golang-jwt/jwt/v5 dependency-version: 5.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c5eaebd23b..0afa9c91ad 100644 --- a/go.mod +++ b/go.mod @@ -79,7 +79,7 @@ require ( github.com/go-openapi/loads v0.22.0 // indirect github.com/go-openapi/spec v0.21.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect diff --git a/go.sum b/go.sum index 6176596f32..fa057131f0 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= From fca613bcb7d006244732d8f625754e7ef62daaee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 20:29:16 +0300 Subject: [PATCH 125/300] CLOUD-727: Bump google.golang.org/grpc from 1.73.0 to 1.74.2 (#1246) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.73.0 to 1.74.2. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.2) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.74.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0afa9c91ad..2442f4a31d 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.40.0 - google.golang.org/grpc v1.73.0 + google.golang.org/grpc v1.74.2 gotest.tools/v3 v3.5.2 k8s.io/api v0.33.3 k8s.io/apimachinery v0.33.3 diff --git a/go.sum b/go.sum index fa057131f0..87f6e4cfa0 100644 --- a/go.sum +++ b/go.sum @@ -311,8 +311,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok= -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc= +google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= +google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= From e655c8bce2c8c5182f580d0d449d5050191b6a73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 20:33:47 +0300 Subject: [PATCH 126/300] CLOUD-727: Bump github.com/onsi/gomega from 1.37.0 to 1.38.0 (#1244) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.37.0 to 1.38.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.37.0...v1.38.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-version: 1.38.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2442f4a31d..a7a577546e 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 github.com/onsi/ginkgo/v2 v2.23.4 - github.com/onsi/gomega v1.37.0 + github.com/onsi/gomega v1.38.0 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 diff --git a/go.sum b/go.sum index 87f6e4cfa0..200ce916af 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= -github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= -github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= +github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= From 2dbc1234d010863cede930a5dcf35ac97e4e4c19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 20:36:16 +0300 Subject: [PATCH 127/300] CLOUD-727: Bump k8s.io/apiextensions-apiserver from 0.33.2 to 0.33.3 (#1241) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.33.2 to 0.33.3. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.33.2...v0.33.3) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.33.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a7a577546e..2b8a4e2b79 100644 --- a/go.mod +++ b/go.mod @@ -129,7 +129,7 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.33.2 + k8s.io/apiextensions-apiserver v0.33.3 k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 diff --git a/go.sum b/go.sum index 200ce916af..1e250bd371 100644 --- a/go.sum +++ b/go.sum @@ -338,8 +338,8 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= -k8s.io/apiextensions-apiserver v0.33.2 h1:6gnkIbngnaUflR3XwE1mCefN3YS8yTD631JXQhsU6M8= -k8s.io/apiextensions-apiserver v0.33.2/go.mod h1:IvVanieYsEHJImTKXGP6XCOjTwv2LUMos0YWc9O+QP8= +k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= +k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= From 4f9621d7105893570516aa31324b1797d41b3722 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 20:38:10 +0300 Subject: [PATCH 128/300] CLOUD-727: Bump github.com/aws/aws-sdk-go from 1.55.7 to 1.55.8 (#1240) Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.55.7 to 1.55.8. - [Release notes](https://github.com/aws/aws-sdk-go/releases) - [Changelog](https://github.com/aws/aws-sdk-go/blob/main/CHANGELOG_PENDING.md) - [Commits](https://github.com/aws/aws-sdk-go/compare/v1.55.7...v1.55.8) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go dependency-version: 1.55.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2b8a4e2b79..1bfe7ce995 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,7 @@ require ( require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go v1.55.7 + github.com/aws/aws-sdk-go v1.55.8 github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/bool64/shared v0.1.5 // indirect diff --git a/go.sum b/go.sum index 1e250bd371..6c7d28a33f 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE= -github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= +github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= From c2f38497fab6954c91593b2cb03b843e990c2b56 Mon Sep 17 00:00:00 2001 From: EvaBnd Date: Fri, 8 Aug 2025 19:38:32 +0200 Subject: [PATCH 129/300] Update LICENSE.md (#1238) Co-authored-by: Viacheslav Sarzhan --- LICENSE.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 093cc59517..45455e2cb4 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,3 +1,15 @@ + Copyright 2017- 2025 Crunchy Data Solution Inc. + + Copyright 2021 - 2025 Percona, LLC + + Licensed under the Apache License, Version 2.0 (the "License");You may not use + this software except in compliance with the License. + A copy of the License can be obtained at: http://www.apache.org/licenses/LICENSE-2.0 + Except as required by applicable law or agreed to in writing, the software distributed + under this License is provided as is, without any warranties or conditions of any kind, + either express or implied. Please refer to the License for the specific terms governing + permissions and limitations. + Apache License Version 2.0, January 2004 @@ -176,8 +188,18 @@ END OF TERMS AND CONDITIONS - Copyright 2017 - 2024 Crunchy Data Solutions, Inc. - Copyright 2021 - 2024 Percona, LLC + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 - 2025 Percona LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 1141943f7a2993d4aa72f147890c73dac6278991 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 21:49:52 +0300 Subject: [PATCH 130/300] CLOUD-727: Bump golang.org/x/tools from 0.35.0 to 0.36.0 (#1250) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.35.0 to 0.36.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.35.0...v0.36.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.36.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 1bfe7ce995..7a7b0c6260 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.40.0 + golang.org/x/crypto v0.41.0 google.golang.org/grpc v1.74.2 gotest.tools/v3 v3.5.2 k8s.io/api v0.33.3 @@ -56,7 +56,7 @@ require ( go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect - golang.org/x/mod v0.26.0 // indirect + golang.org/x/mod v0.27.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect ) @@ -115,14 +115,14 @@ require ( go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.42.0 // indirect + golang.org/x/net v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/term v0.33.0 // indirect - golang.org/x/text v0.27.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/term v0.34.0 // indirect + golang.org/x/text v0.28.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.35.0 + golang.org/x/tools v0.36.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect diff --git a/go.sum b/go.sum index 6c7d28a33f..073f1d92f6 100644 --- a/go.sum +++ b/go.sum @@ -249,21 +249,21 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= -golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -280,18 +280,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -299,8 +299,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From e26eaebdcc13e0e19509d3b323c1045b4d3329ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 22:00:09 +0300 Subject: [PATCH 131/300] CLOUD-727: Bump github.com/go-openapi/errors from 0.22.1 to 0.22.2 (#1252) Bumps [github.com/go-openapi/errors](https://github.com/go-openapi/errors) from 0.22.1 to 0.22.2. - [Commits](https://github.com/go-openapi/errors/compare/v0.22.1...v0.22.2) --- updated-dependencies: - dependency-name: github.com/go-openapi/errors dependency-version: 0.22.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7a7b0c6260..bf3a5785ba 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.24.1 require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc github.com/go-logr/logr v1.4.3 - github.com/go-openapi/errors v0.22.1 + github.com/go-openapi/errors v0.22.2 github.com/go-openapi/runtime v0.28.0 github.com/go-openapi/strfmt v0.23.0 github.com/go-openapi/swag v0.23.1 diff --git a/go.sum b/go.sum index 073f1d92f6..d7a385eba8 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU= -github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= +github.com/go-openapi/errors v0.22.2 h1:rdxhzcBUazEcGccKqbY1Y7NS8FDcMyIRr0934jrYnZg= +github.com/go-openapi/errors v0.22.2/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= From a1be2f8c81166c3394a08a2bd5c82ebde3c03374 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 22:26:51 +0300 Subject: [PATCH 132/300] CLOUD-727: Bump k8s.io/apiextensions-apiserver from 0.33.3 to 0.33.4 (#1253) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.33.3 to 0.33.4. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.33.3...v0.33.4) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.33.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index bf3a5785ba..ae4991f331 100644 --- a/go.mod +++ b/go.mod @@ -34,10 +34,10 @@ require ( golang.org/x/crypto v0.41.0 google.golang.org/grpc v1.74.2 gotest.tools/v3 v3.5.2 - k8s.io/api v0.33.3 - k8s.io/apimachinery v0.33.3 - k8s.io/client-go v0.33.3 - k8s.io/component-base v0.33.3 + k8s.io/api v0.33.4 + k8s.io/apimachinery v0.33.4 + k8s.io/client-go v0.33.4 + k8s.io/component-base v0.33.4 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.6.0 ) @@ -129,7 +129,7 @@ require ( google.golang.org/protobuf v1.36.6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.33.3 + k8s.io/apiextensions-apiserver v0.33.4 k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 diff --git a/go.sum b/go.sum index d7a385eba8..54115d96d6 100644 --- a/go.sum +++ b/go.sum @@ -336,16 +336,16 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8= -k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE= -k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs= -k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8= -k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA= -k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA= -k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg= -k8s.io/component-base v0.33.3 h1:mlAuyJqyPlKZM7FyaoM/LcunZaaY353RXiOd2+B5tGA= -k8s.io/component-base v0.33.3/go.mod h1:ktBVsBzkI3imDuxYXmVxZ2zxJnYTZ4HAsVj9iF09qp4= +k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk= +k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc= +k8s.io/apiextensions-apiserver v0.33.4 h1:rtq5SeXiDbXmSwxsF0MLe2Mtv3SwprA6wp+5qh/CrOU= +k8s.io/apiextensions-apiserver v0.33.4/go.mod h1:mWXcZQkQV1GQyxeIjYApuqsn/081hhXPZwZ2URuJeSs= +k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s= +k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= +k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw= +k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY= +k8s.io/component-base v0.33.4 h1:Jvb/aw/tl3pfgnJ0E0qPuYLT0NwdYs1VXXYQmSuxJGY= +k8s.io/component-base v0.33.4/go.mod h1:567TeSdixWW2Xb1yYUQ7qk5Docp2kNznKL87eygY8Rc= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= From b98693f2e0c22969056f5c2f4fec1752b2da01b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Aug 2025 11:45:57 +0300 Subject: [PATCH 133/300] CLOUD-727: Bump github.com/onsi/ginkgo/v2 from 2.23.4 to 2.24.0 (#1257) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.23.4 to 2.24.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.23.4...v2.24.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-version: 2.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 3 ++- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ae4991f331..83df5272dd 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.7.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 - github.com/onsi/ginkgo/v2 v2.23.4 + github.com/onsi/ginkgo/v2 v2.24.0 github.com/onsi/gomega v1.38.0 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 @@ -43,6 +43,7 @@ require ( ) require ( + github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect diff --git a/go.sum b/go.sum index 54115d96d6..45b92e1c5d 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc h1:aBpUepmWt8NsLH0fOA6vb8CCvIIJ4jMNxpvR36PaRSs= github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc/go.mod h1:dOzRkbUNd/qpn35nOSy60ZQBiP9wa9g1kh9kaMg/tOk= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -143,8 +145,8 @@ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= -github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= -github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= +github.com/onsi/ginkgo/v2 v2.24.0 h1:obZz8LAnHicNdbBqvG3ytAFx8fgza+i1IDpBVcHT2YE= +github.com/onsi/ginkgo/v2 v2.24.0/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= From 324ba167213d7a60f6d9eb8b1102a31670e20b5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 23:18:55 +0300 Subject: [PATCH 134/300] CLOUD-727: Bump github.com/onsi/ginkgo/v2 from 2.23.4 to 2.25.1 (#1261) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.23.4 to 2.25.1. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.23.4...v2.25.1) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 83df5272dd..c6c53c44f3 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.7.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 - github.com/onsi/ginkgo/v2 v2.24.0 + github.com/onsi/ginkgo/v2 v2.25.1 github.com/onsi/gomega v1.38.0 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 45b92e1c5d..a34ac98733 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= -github.com/onsi/ginkgo/v2 v2.24.0 h1:obZz8LAnHicNdbBqvG3ytAFx8fgza+i1IDpBVcHT2YE= -github.com/onsi/ginkgo/v2 v2.24.0/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= +github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY= +github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= From 00fae569d2f2421db6d7b9347c0128bd0edad347 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:03:54 +0300 Subject: [PATCH 135/300] CLOUD-727: Bump go.nhat.io/grpcmock from 0.31.0 to 0.32.0 (#1263) Bumps [go.nhat.io/grpcmock](https://github.com/nhatthm/grpcmock) from 0.31.0 to 0.32.0. - [Release notes](https://github.com/nhatthm/grpcmock/releases) - [Commits](https://github.com/nhatthm/grpcmock/compare/v0.31.0...v0.32.0) --- updated-dependencies: - dependency-name: go.nhat.io/grpcmock dependency-version: 0.32.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c6c53c44f3..a62c370056 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 - go.nhat.io/grpcmock v0.31.0 + go.nhat.io/grpcmock v0.32.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 go.opentelemetry.io/otel v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 @@ -127,7 +127,7 @@ require ( gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect - google.golang.org/protobuf v1.36.6 // indirect + google.golang.org/protobuf v1.36.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.33.4 diff --git a/go.sum b/go.sum index a34ac98733..beab94c835 100644 --- a/go.sum +++ b/go.sum @@ -207,8 +207,8 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.nhat.io/aferomock v0.8.0 h1:jESv25NuTpA/Wga+AOKqKI1lPKdYiBYvxpIUDJWyfPM= go.nhat.io/aferomock v0.8.0/go.mod h1:thJD/9Yeo+CcIW45u6rNU8WYc1yIWdqfOSpKcGtjAXw= -go.nhat.io/grpcmock v0.31.0 h1:UK7xeS0qGY/duLnKMvCb3JtR9fy9GQ2/MbEsrFvkXIE= -go.nhat.io/grpcmock v0.31.0/go.mod h1:BuY58zdX1LWnC4kkjvkK+fpIC69P4lNQMjL/6++KaD4= +go.nhat.io/grpcmock v0.32.0 h1:0qAwlE7Tc8paLbQ3TbwmucsrjW7+D3M68ozJYFWp+5c= +go.nhat.io/grpcmock v0.32.0/go.mod h1:6LzGOzY7X8cVyJBSdOMG13RqiEGDIqFy9mJedUPj5NA= go.nhat.io/matcher/v2 v2.0.0 h1:W+rbHi0hKuZHtOQH4U5g+KwyKyfVioIxrxjoGRcUETE= go.nhat.io/matcher/v2 v2.0.0/go.mod h1:cL5oYp0M9A4L8jEGqjmUfy+k7AXVDddoVt6aYIL1r5g= go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= @@ -317,8 +317,8 @@ google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 8919e0ee00b4e2e4c04bdff838acc0f4ff756a81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:04:09 +0300 Subject: [PATCH 136/300] CLOUD-727: Bump actions/checkout from 4 to 5 (#1267) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- .github/workflows/reviewdog.yml | 16 ++++++++-------- .github/workflows/scan.yml | 2 +- .github/workflows/test.yml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 6a3caaa223..7df94fb822 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -8,7 +8,7 @@ jobs: - uses: actions/setup-go@v5 with: go-version: '^1.23' - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: golangci-lint uses: golangci/golangci-lint-action@v8 with: @@ -20,7 +20,7 @@ jobs: name: runner / suggester / goimports-reviser runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version: '^1.23' @@ -34,7 +34,7 @@ jobs: name: runner / suggester / gofmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: gofmt -w -s $(find . -not -path "*/vendor/*" -name "*.go") - uses: reviewdog/action-suggester@v1 with: @@ -44,7 +44,7 @@ jobs: name: runner / suggester / shfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version: '^1.23' @@ -60,7 +60,7 @@ jobs: name: runner / shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: reviewdog/action-shellcheck@v1 with: github_token: ${{ secrets.github_token }} @@ -70,7 +70,7 @@ jobs: name: runner / misspell runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: reviewdog/action-misspell@v1 with: github_token: ${{ secrets.github_token }} @@ -81,7 +81,7 @@ jobs: name: runner / alex runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: reviewdog/action-alex@v1 with: github_token: ${{ secrets.github_token }} @@ -92,7 +92,7 @@ jobs: name: runner / manifests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: | make generate VERSION=main git diff --exit-code diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index a776fdfb11..6366a5f9a2 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 504c3fa2b1..e9ced8ecb8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,12 +6,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone the code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Go uses: actions/setup-go@v5 with: go-version: '^1.23' - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Basic tests run: make check - name: envtest From bcd3177a7cc12e57581d2a3ef3dea2baf2d2a6cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:04:28 +0300 Subject: [PATCH 137/300] CLOUD-727: Bump aquasecurity/trivy-action from 0.32.0 to 0.33.0 (#1266) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.32.0 to 0.33.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.32.0...0.33.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- .github/workflows/scan.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 6366a5f9a2..2bbb9ad862 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -31,7 +31,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/arm64) - uses: aquasecurity/trivy-action@0.32.0 + uses: aquasecurity/trivy-action@0.33.0 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64' format: 'table' @@ -50,7 +50,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/amd64) - uses: aquasecurity/trivy-action@0.32.0 + uses: aquasecurity/trivy-action@0.33.0 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64' format: 'table' From be6a192e8515338ee778b32892b555ff8f03221e Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 22 Sep 2025 16:15:19 +0300 Subject: [PATCH 138/300] K8SPG-719 check sts generation before and after rotating the pmm3 token (#1281) * K8SPG-719 check sts generation before and after rotation the pmm3 token * fix total timeout --- e2e-tests/functions | 19 +++++++++++++++++++ .../04-update-pmm-server-token.yaml | 14 +++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 1b0290d79d..8a11e0fed4 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -1065,3 +1065,22 @@ get_postgresql_logs() { | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null done } + +wait_for_generation() { + local resource="$1" + local target_generation="$2" + + echo "Waiting for $resource to reach generation $target_generation..." + + while true; do + current_generation=$(kubectl -n ${NAMESPACE} get "$resource" -o jsonpath='{.metadata.generation}') + + if [ "$current_generation" -eq "$target_generation" ]; then + echo "Resource $resource has reached generation $target_generation." + break + else + echo "Resource $resource is at generation $current_generation. Waiting..." + sleep 5 + fi + done +} diff --git a/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml b/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml index 8c83a3d2f8..c164d9ee3e 100644 --- a/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml +++ b/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml @@ -1,16 +1,28 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep -timeout: 25 +timeout: 60 commands: - script: |- set -o errexit set -o xtrace source ../../functions + + sts=$(kubectl -n "${NAMESPACE}" get sts --selector=postgres-operator.crunchydata.com/instance-set=instance1 -o jsonpath='{.items[*].metadata.name}') + for st in $sts; do + wait_for_generation "sts/$st" 2 + done token=$(generate_pmm3_server_token) [[ -n ${token} && ${token} != null ]] \ && kubectl -n ${NAMESPACE} patch secret monitoring-pmm3-pmm-secret --type merge --patch '{"stringData": {"PMM_SERVER_TOKEN": "'${token}'"}}' \ || true + + sleep 10 + + sts=$(kubectl -n "${NAMESPACE}" get sts --selector=postgres-operator.crunchydata.com/instance-set=instance1 -o jsonpath='{.items[*].metadata.name}') + for st in $sts; do + wait_for_generation "sts/$st" 3 + done sleep 25 From 0de607ce1477dfbb60a109dd832fdd5dc36575c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 24 Sep 2025 15:24:41 +0300 Subject: [PATCH 139/300] K8SPG-718: Fix timeout in monitoring-pmm3 (#1282) --- .../monitoring-pmm3/04-update-pmm-server-token.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml b/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml index c164d9ee3e..838d03b290 100644 --- a/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml +++ b/e2e-tests/tests/monitoring-pmm3/04-update-pmm-server-token.yaml @@ -1,13 +1,13 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep -timeout: 60 commands: - - script: |- + - timeout: 60 + script: |- set -o errexit set -o xtrace source ../../functions - + sts=$(kubectl -n "${NAMESPACE}" get sts --selector=postgres-operator.crunchydata.com/instance-set=instance1 -o jsonpath='{.items[*].metadata.name}') for st in $sts; do wait_for_generation "sts/$st" 2 @@ -17,9 +17,9 @@ commands: [[ -n ${token} && ${token} != null ]] \ && kubectl -n ${NAMESPACE} patch secret monitoring-pmm3-pmm-secret --type merge --patch '{"stringData": {"PMM_SERVER_TOKEN": "'${token}'"}}' \ || true - + sleep 10 - + sts=$(kubectl -n "${NAMESPACE}" get sts --selector=postgres-operator.crunchydata.com/instance-set=instance1 -o jsonpath='{.items[*].metadata.name}') for st in $sts; do wait_for_generation "sts/$st" 3 From f79ca4f8d313f3a34ac44e7369559635dce5853f Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 24 Sep 2025 15:25:09 +0300 Subject: [PATCH 140/300] K8SPG-570 treat user-created secrets with operator default secret name as custom (#1283) Co-authored-by: Viacheslav Sarzhan --- internal/controller/postgrescluster/postgres.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/controller/postgrescluster/postgres.go b/internal/controller/postgrescluster/postgres.go index 3064cedc5b..fff61cf07c 100644 --- a/internal/controller/postgrescluster/postgres.go +++ b/internal/controller/postgrescluster/postgres.go @@ -501,10 +501,8 @@ func (r *Reconciler) reconcilePostgresUserSecrets( // with the right labels so that the selector called next to track them // and utilize their data. for _, user := range specUsers { - if user.SecretName != "" { - if err := r.updateCustomSecretLabels(ctx, cluster, user); err != nil { - return specUsers, nil, err - } + if err := r.updateCustomSecretLabels(ctx, cluster, user); err != nil { + return specUsers, nil, err } } @@ -603,8 +601,12 @@ func (r *Reconciler) reconcilePostgresUserSecrets( func (r *Reconciler) updateCustomSecretLabels( ctx context.Context, cluster *v1beta1.PostgresCluster, user v1beta1.PostgresUserSpec, ) error { - secretName := string(user.SecretName) + userName := string(user.Name) + secretName := naming.PostgresUserSecret(cluster, userName).Name + if user.SecretName != "" { + secretName = string(user.SecretName) + } secret := &corev1.Secret{} err := r.Client.Get(ctx, types.NamespacedName{ From 2073269b153e827ec18924e8eb676434a1817164 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 12:46:47 +0300 Subject: [PATCH 141/300] CLOUD-727: Bump k8s.io/client-go from 0.33.4 to 0.34.1 (#1279) * CLOUD-727: Bump k8s.io/client-go from 0.33.4 to 0.34.1 Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.33.4 to 0.34.1. - [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md) - [Commits](https://github.com/kubernetes/client-go/compare/v0.33.4...v0.34.1) --- updated-dependencies: - dependency-name: k8s.io/client-go dependency-version: 0.34.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * remove from generate upgrade job test the creationTimestamp: null * remove meta null creation type from TestMetadataGetLabels * TestService fix for null creation * fix TestGeneratePGAdminConfigMap/Data,ObjectMeta,TypeMeta by removing null creation date * remove from multiple tests creationTimestamp: null * Update internal/controller/postgrescluster/pgadmin_test.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update internal/controller/postgrescluster/pgadmin_test.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update internal/controller/postgrescluster/pgadmin_test.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update internal/controller/postgrescluster/pgadmin_test.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update internal/controller/postgrescluster/pgadmin_test.go Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * run make generate main --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: George Kechagias Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- ...ator.crunchydata.com_postgresclusters.yaml | 1332 +++++++- .../pgv2.percona.com_perconapgbackups.yaml | 8 +- .../pgv2.percona.com_perconapgclusters.yaml | 1007 +++++- .../pgv2.percona.com_perconapgupgrades.yaml | 118 +- .../pgv2.percona.com_perconapgclusters.yaml | 1133 ++++++- ...res-operator.crunchydata.com_pgadmins.yaml | 119 +- ...s-operator.crunchydata.com_pgupgrades.yaml | 118 +- ...ator.crunchydata.com_postgresclusters.yaml | 1332 +++++++- deploy/bundle.yaml | 2702 +++++++++++++++-- deploy/crd.yaml | 2702 +++++++++++++++-- deploy/cw-bundle.yaml | 2702 +++++++++++++++-- go.mod | 25 +- go.sum | 54 +- internal/controller/pgupgrade/jobs_test.go | 4 - .../postgrescluster/cluster_test.go | 3 - .../postgrescluster/patroni_test.go | 1 - .../postgrescluster/pgadmin_test.go | 5 - .../postgrescluster/pgbouncer_test.go | 3 - .../standalone_pgadmin/configmap_test.go | 1 - .../standalone_pgadmin/service_test.go | 1 - .../standalone_pgadmin/statefulset_test.go | 2 - .../v1beta1/postgrescluster_test.go | 6 +- 22 files changed, 12020 insertions(+), 1358 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 0f458588d8..0b69f54392 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -285,6 +285,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -381,8 +486,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -440,6 +546,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -519,8 +662,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -765,7 +909,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1404,8 +1548,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -1772,7 +1916,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2739,8 +2883,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -3104,7 +3248,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3435,8 +3579,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -3495,6 +3640,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -3558,8 +3740,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -3586,9 +3768,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -4275,7 +4457,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4330,10 +4512,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -4345,6 +4527,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -5453,15 +5688,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6068,8 +6301,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -6462,7 +6695,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6574,7 +6807,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6639,7 +6872,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6938,6 +7171,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -7805,8 +8143,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -8393,6 +8731,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -8767,15 +9210,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -8802,7 +9243,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9487,8 +9928,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -9874,7 +10315,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10462,7 +10903,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11099,8 +11540,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -11490,8 +11931,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -11549,6 +11991,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -11610,8 +12089,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -11638,8 +12117,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -12316,7 +12796,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12371,10 +12851,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -12386,6 +12866,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -13065,15 +13598,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -13092,8 +13623,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -13151,6 +13683,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -13230,8 +13799,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -13463,7 +14033,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13563,8 +14133,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -13622,6 +14193,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -13683,8 +14291,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -13711,8 +14319,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -14389,7 +14998,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14444,10 +15053,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -14459,6 +15068,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -15008,7 +15670,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15307,7 +15969,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15551,15 +16213,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16049,15 +16709,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16342,6 +17000,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -16505,7 +17268,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -17249,8 +18012,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -17859,6 +18622,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -18008,8 +18876,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -18068,6 +18937,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18130,8 +19036,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -18158,8 +19064,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -18838,7 +19745,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18893,10 +19800,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -18908,6 +19815,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -19477,8 +20437,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -19536,6 +20497,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -19615,8 +20613,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -19699,7 +20698,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -20058,7 +21057,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -21086,8 +22085,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -21680,6 +22679,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -21982,15 +23086,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -22045,7 +23147,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml index a5f789b146..2961b92519 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml @@ -367,15 +367,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index ff79e1f5ab..3245fe267d 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -309,6 +309,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -413,7 +518,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -478,7 +583,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -539,8 +644,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -598,6 +704,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -677,8 +820,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -923,7 +1067,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1562,8 +1706,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -1930,7 +2074,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2897,8 +3041,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -3262,7 +3406,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3593,8 +3737,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -3653,6 +3798,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -3716,8 +3898,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -3744,9 +3926,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -4433,7 +4615,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4488,10 +4670,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -4503,6 +4685,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -5611,15 +5846,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6226,8 +6459,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -6620,7 +6853,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6732,7 +6965,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6797,7 +7030,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7453,8 +7686,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -8041,6 +8274,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -8415,15 +8753,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -8450,7 +8786,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9135,8 +9471,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -9522,7 +9858,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10287,7 +10623,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10924,8 +11260,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -11285,7 +11621,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11518,15 +11854,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -11544,8 +11878,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -11603,6 +11938,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -11681,8 +12053,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -11914,7 +12287,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12014,8 +12387,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12073,6 +12447,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12134,8 +12545,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -12162,8 +12573,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -12840,7 +13252,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12895,10 +13307,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -12910,6 +13322,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -13459,7 +13924,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13788,8 +14253,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -13847,6 +14313,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -13908,8 +14411,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -13936,8 +14439,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -14614,7 +15118,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14669,10 +15173,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -14684,6 +15188,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -15374,15 +15931,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -15872,15 +16427,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16231,7 +16784,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -16892,8 +17445,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -17502,6 +18055,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -17621,7 +18279,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -17742,8 +18400,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -17801,6 +18460,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -17879,8 +18575,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -18006,7 +18703,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18336,8 +19033,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -18396,6 +19094,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18458,8 +19193,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -18486,8 +19221,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -19166,7 +19902,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19221,10 +19957,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -19236,6 +19972,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml index 4d8151b507..c861a27fd4 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml @@ -609,8 +609,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -1035,8 +1035,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1094,6 +1095,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1154,8 +1192,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -1182,8 +1220,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -1854,7 +1893,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1908,10 +1947,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -1923,6 +1962,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -2451,7 +2543,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 8f6b7eb916..d5b8c6b285 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -366,15 +366,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -716,6 +714,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -820,7 +923,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -885,7 +988,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -946,8 +1049,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1005,6 +1109,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1084,8 +1225,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -1330,7 +1472,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1969,8 +2111,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -2337,7 +2479,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3304,8 +3446,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -3669,7 +3811,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4000,8 +4142,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -4060,6 +4203,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -4123,8 +4303,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -4151,9 +4331,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -4840,7 +5020,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4895,10 +5075,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -4910,6 +5090,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -6018,15 +6251,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6633,8 +6864,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -7027,7 +7258,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7139,7 +7370,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7204,7 +7435,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7860,8 +8091,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -8448,6 +8679,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -8822,15 +9158,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -8857,7 +9191,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9542,8 +9876,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -9929,7 +10263,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10694,7 +11028,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11331,8 +11665,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -11692,7 +12026,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11925,15 +12259,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -11951,8 +12283,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12010,6 +12343,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12088,8 +12458,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -12321,7 +12692,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12421,8 +12792,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12480,6 +12852,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12541,8 +12950,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -12569,8 +12978,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -13247,7 +13657,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13302,10 +13712,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -13317,6 +13727,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -13866,7 +14329,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14195,8 +14658,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -14254,6 +14718,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -14315,8 +14816,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -14343,8 +14844,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -15021,7 +15523,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15076,10 +15578,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -15091,6 +15593,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -15781,15 +16336,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16279,15 +16832,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16638,7 +17189,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -17299,8 +17850,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -17909,6 +18460,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -18028,7 +18684,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18149,8 +18805,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -18208,6 +18865,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18286,8 +18980,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -18413,7 +19108,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18743,8 +19438,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -18803,6 +19499,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18865,8 +19598,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -18893,8 +19626,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -19573,7 +20307,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19628,10 +20362,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -19643,6 +20377,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -21721,8 +22508,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -22147,8 +22934,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -22206,6 +22994,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -22266,8 +23091,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -22294,8 +23119,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -22966,7 +23792,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -23020,10 +23846,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -23035,6 +23861,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -23563,7 +24442,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml index f2b51f4ee6..5820ff691c 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml @@ -612,8 +612,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -1210,6 +1210,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -1508,15 +1613,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -1584,7 +1687,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml index 2e9319c8cc..db71b1a270 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml @@ -612,8 +612,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -1033,8 +1033,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1092,6 +1093,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1152,8 +1190,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -1180,8 +1218,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -1852,7 +1891,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1906,10 +1945,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -1921,6 +1960,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -2449,7 +2541,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 2b15ddaeaa..a950d40cc9 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -282,6 +282,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -373,8 +478,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -432,6 +538,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -511,8 +654,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -757,7 +901,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1396,8 +1540,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -1764,7 +1908,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2731,8 +2875,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -3096,7 +3240,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3427,8 +3571,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -3487,6 +3632,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -3550,8 +3732,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -3578,9 +3760,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -4267,7 +4449,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4322,10 +4504,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -4337,6 +4519,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -5440,15 +5675,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6058,8 +6291,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -6452,7 +6685,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6564,7 +6797,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6629,7 +6862,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -6923,6 +7156,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -7775,8 +8113,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -8358,6 +8696,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -8727,15 +9170,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -8762,7 +9203,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9447,8 +9888,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -9834,7 +10275,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10417,7 +10858,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11054,8 +11495,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -11445,8 +11886,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -11500,6 +11942,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -11557,8 +12036,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -11581,8 +12060,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -12251,7 +12731,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12306,10 +12786,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -12321,6 +12801,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -13004,15 +13537,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -13034,8 +13565,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -13093,6 +13625,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -13172,8 +13741,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -13405,7 +13975,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13505,8 +14075,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -13564,6 +14135,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -13625,8 +14233,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -13653,8 +14261,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -14331,7 +14940,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14386,10 +14995,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -14401,6 +15010,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -14950,7 +15612,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15249,7 +15911,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15493,15 +16155,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -15996,15 +16656,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16288,6 +16946,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -16447,7 +17210,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -17191,8 +17954,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -17797,6 +18560,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -17942,8 +18810,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -17998,6 +18867,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18056,8 +18962,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -18080,8 +18986,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -18752,7 +19659,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18807,10 +19714,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -18822,6 +19729,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -19386,8 +20346,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -19445,6 +20406,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -19524,8 +20522,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -19608,7 +20607,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19967,7 +20966,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -20997,8 +21996,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -21587,6 +22586,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -21880,15 +22984,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -21943,7 +23045,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 9d26c605c0..d7a01c53c4 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -661,15 +661,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -1013,6 +1011,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -1117,7 +1220,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1182,7 +1285,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1243,8 +1346,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1302,6 +1406,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1381,8 +1522,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -1627,7 +1769,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2266,8 +2408,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -2634,7 +2776,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3601,8 +3743,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -3966,7 +4108,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4297,8 +4439,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -4357,6 +4500,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -4420,8 +4600,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -4448,9 +4628,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -5137,7 +5317,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -5192,10 +5372,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -5207,6 +5387,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -6315,15 +6548,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6930,8 +7161,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -7324,7 +7555,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7436,7 +7667,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7501,7 +7732,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -8157,8 +8388,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -8745,6 +8976,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -9119,15 +9455,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -9154,7 +9488,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9839,8 +10173,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -10226,7 +10560,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10991,7 +11325,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11628,8 +11962,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -11989,7 +12323,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12222,15 +12556,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -12248,8 +12580,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12307,6 +12640,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12385,8 +12755,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -12618,7 +12989,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12718,8 +13089,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12777,6 +13149,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12838,8 +13247,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -12866,8 +13275,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -13544,7 +13954,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13599,10 +14009,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -13614,6 +14024,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -14163,7 +14626,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14492,8 +14955,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -14551,6 +15015,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -14612,8 +15113,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -14640,8 +15141,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -15318,7 +15820,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15373,10 +15875,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -15388,6 +15890,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -16078,15 +16633,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16576,15 +17129,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16935,7 +17486,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -17596,8 +18147,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -18206,6 +18757,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -18325,7 +18981,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18446,8 +19102,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -18505,6 +19162,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18583,8 +19277,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -18710,7 +19405,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19040,8 +19735,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -19100,6 +19796,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -19162,8 +19895,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -19190,8 +19923,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -19870,7 +20604,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19925,10 +20659,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -19940,6 +20674,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -22022,8 +22809,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -22448,8 +23235,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -22507,6 +23295,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -22567,8 +23392,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -22595,8 +23420,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -23267,7 +24093,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -23321,10 +24147,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -23336,6 +24162,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -23864,7 +24743,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -24736,8 +25615,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -25334,6 +26213,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -25632,15 +26616,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -25708,7 +26690,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -26632,8 +27614,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -27053,8 +28035,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -27112,6 +28095,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -27172,8 +28192,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -27200,8 +28220,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -27872,7 +28893,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -27926,10 +28947,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -27941,6 +28962,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -28469,7 +29543,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -29001,6 +30075,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -29092,8 +30271,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -29151,6 +30331,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -29230,8 +30447,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -29476,7 +30694,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -30115,8 +31333,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -30483,7 +31701,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -31450,8 +32668,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -31815,7 +33033,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -32146,8 +33364,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -32206,6 +33425,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -32269,8 +33525,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -32297,9 +33553,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -32986,7 +34242,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -33041,10 +34297,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -33056,6 +34312,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -34159,15 +35468,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -34777,8 +36084,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -35171,7 +36478,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35283,7 +36590,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35348,7 +36655,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35642,6 +36949,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -36494,8 +37906,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -37077,6 +38489,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -37446,15 +38963,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -37481,7 +38996,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -38166,8 +39681,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -38553,7 +40068,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -39136,7 +40651,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -39773,8 +41288,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -40164,8 +41679,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -40219,6 +41735,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -40276,8 +41829,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -40300,8 +41853,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -40970,7 +42524,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -41025,10 +42579,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -41040,6 +42594,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -41723,15 +43330,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -41753,8 +43358,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -41812,6 +43418,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -41891,8 +43534,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -42124,7 +43768,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -42224,8 +43868,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -42283,6 +43928,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -42344,8 +44026,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -42372,8 +44054,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -43050,7 +44733,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -43105,10 +44788,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -43120,6 +44803,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -43669,7 +45405,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -43968,7 +45704,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -44212,15 +45948,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -44715,15 +46449,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -45007,6 +46739,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -45166,7 +47003,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -45910,8 +47747,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -46516,6 +48353,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -46661,8 +48603,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -46717,6 +48660,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -46775,8 +48755,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -46799,8 +48779,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -47471,7 +49452,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -47526,10 +49507,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -47541,6 +49522,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -48105,8 +50139,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -48164,6 +50199,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -48243,8 +50315,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -48327,7 +50400,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -48686,7 +50759,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -49716,8 +51789,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -50306,6 +52379,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -50599,15 +52777,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -50662,7 +52838,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 556c385de9..2dfe715be9 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -661,15 +661,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -1013,6 +1011,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -1117,7 +1220,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1182,7 +1285,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1243,8 +1346,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1302,6 +1406,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1381,8 +1522,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -1627,7 +1769,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2266,8 +2408,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -2634,7 +2776,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3601,8 +3743,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -3966,7 +4108,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4297,8 +4439,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -4357,6 +4500,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -4420,8 +4600,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -4448,9 +4628,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -5137,7 +5317,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -5192,10 +5372,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -5207,6 +5387,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -6315,15 +6548,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6930,8 +7161,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -7324,7 +7555,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7436,7 +7667,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7501,7 +7732,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -8157,8 +8388,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -8745,6 +8976,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -9119,15 +9455,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -9154,7 +9488,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9839,8 +10173,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -10226,7 +10560,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10991,7 +11325,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11628,8 +11962,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -11989,7 +12323,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12222,15 +12556,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -12248,8 +12580,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12307,6 +12640,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12385,8 +12755,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -12618,7 +12989,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12718,8 +13089,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12777,6 +13149,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12838,8 +13247,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -12866,8 +13275,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -13544,7 +13954,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13599,10 +14009,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -13614,6 +14024,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -14163,7 +14626,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14492,8 +14955,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -14551,6 +15015,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -14612,8 +15113,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -14640,8 +15141,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -15318,7 +15820,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15373,10 +15875,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -15388,6 +15890,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -16078,15 +16633,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16576,15 +17129,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16935,7 +17486,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -17596,8 +18147,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -18206,6 +18757,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -18325,7 +18981,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18446,8 +19102,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -18505,6 +19162,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18583,8 +19277,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -18710,7 +19405,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19040,8 +19735,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -19100,6 +19796,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -19162,8 +19895,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -19190,8 +19923,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -19870,7 +20604,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19925,10 +20659,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -19940,6 +20674,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -22022,8 +22809,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -22448,8 +23235,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -22507,6 +23295,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -22567,8 +23392,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -22595,8 +23420,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -23267,7 +24093,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -23321,10 +24147,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -23336,6 +24162,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -23864,7 +24743,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -24736,8 +25615,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -25334,6 +26213,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -25632,15 +26616,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -25708,7 +26690,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -26632,8 +27614,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -27053,8 +28035,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -27112,6 +28095,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -27172,8 +28192,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -27200,8 +28220,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -27872,7 +28893,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -27926,10 +28947,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -27941,6 +28962,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -28469,7 +29543,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -29001,6 +30075,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -29092,8 +30271,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -29151,6 +30331,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -29230,8 +30447,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -29476,7 +30694,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -30115,8 +31333,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -30483,7 +31701,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -31450,8 +32668,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -31815,7 +33033,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -32146,8 +33364,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -32206,6 +33425,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -32269,8 +33525,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -32297,9 +33553,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -32986,7 +34242,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -33041,10 +34297,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -33056,6 +34312,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -34159,15 +35468,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -34777,8 +36084,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -35171,7 +36478,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35283,7 +36590,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35348,7 +36655,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35642,6 +36949,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -36494,8 +37906,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -37077,6 +38489,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -37446,15 +38963,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -37481,7 +38996,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -38166,8 +39681,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -38553,7 +40068,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -39136,7 +40651,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -39773,8 +41288,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -40164,8 +41679,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -40219,6 +41735,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -40276,8 +41829,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -40300,8 +41853,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -40970,7 +42524,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -41025,10 +42579,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -41040,6 +42594,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -41723,15 +43330,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -41753,8 +43358,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -41812,6 +43418,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -41891,8 +43534,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -42124,7 +43768,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -42224,8 +43868,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -42283,6 +43928,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -42344,8 +44026,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -42372,8 +44054,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -43050,7 +44733,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -43105,10 +44788,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -43120,6 +44803,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -43669,7 +45405,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -43968,7 +45704,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -44212,15 +45948,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -44715,15 +46449,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -45007,6 +46739,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -45166,7 +47003,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -45910,8 +47747,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -46516,6 +48353,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -46661,8 +48603,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -46717,6 +48660,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -46775,8 +48755,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -46799,8 +48779,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -47471,7 +49452,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -47526,10 +49507,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -47541,6 +49522,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -48105,8 +50139,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -48164,6 +50199,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -48243,8 +50315,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -48327,7 +50400,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -48686,7 +50759,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -49716,8 +51789,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -50306,6 +52379,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -50599,15 +52777,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -50662,7 +52838,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 9553c74d7a..526eb5d9eb 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -661,15 +661,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -1013,6 +1011,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -1117,7 +1220,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1182,7 +1285,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1243,8 +1346,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1302,6 +1406,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1381,8 +1522,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -1627,7 +1769,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2266,8 +2408,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -2634,7 +2776,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -3601,8 +3743,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -3966,7 +4108,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4297,8 +4439,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -4357,6 +4500,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -4420,8 +4600,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -4448,9 +4628,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -5137,7 +5317,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -5192,10 +5372,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -5207,6 +5387,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -6315,15 +6548,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6930,8 +7161,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -7324,7 +7555,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7436,7 +7667,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7501,7 +7732,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -8157,8 +8388,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -8745,6 +8976,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -9119,15 +9455,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -9154,7 +9488,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -9839,8 +10173,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -10226,7 +10560,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -10991,7 +11325,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -11628,8 +11962,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -11989,7 +12323,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12222,15 +12556,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -12248,8 +12580,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12307,6 +12640,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12385,8 +12755,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -12618,7 +12989,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -12718,8 +13089,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -12777,6 +13149,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -12838,8 +13247,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -12866,8 +13275,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -13544,7 +13954,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -13599,10 +14009,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -13614,6 +14024,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -14163,7 +14626,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -14492,8 +14955,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -14551,6 +15015,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -14612,8 +15113,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -14640,8 +15141,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -15318,7 +15820,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -15373,10 +15875,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -15388,6 +15890,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -16078,15 +16633,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16576,15 +17129,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -16935,7 +17486,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -17596,8 +18147,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -18206,6 +18757,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -18325,7 +18981,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -18446,8 +19102,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -18505,6 +19162,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -18583,8 +19277,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -18710,7 +19405,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19040,8 +19735,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -19100,6 +19796,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -19162,8 +19895,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -19190,8 +19923,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -19870,7 +20604,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -19925,10 +20659,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -19940,6 +20674,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -22022,8 +22809,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -22448,8 +23235,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -22507,6 +23295,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -22567,8 +23392,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -22595,8 +23420,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -23267,7 +24093,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -23321,10 +24147,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -23336,6 +24162,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -23864,7 +24743,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -24736,8 +25615,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -25334,6 +26213,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -25632,15 +26616,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -25708,7 +26690,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -26632,8 +27614,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -27053,8 +28035,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -27112,6 +28095,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -27172,8 +28192,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -27200,8 +28220,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -27872,7 +28893,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -27926,10 +28947,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -27941,6 +28962,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -28469,7 +29543,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -29001,6 +30075,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -29092,8 +30271,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -29151,6 +30331,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -29230,8 +30447,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -29476,7 +30694,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -30115,8 +31333,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -30483,7 +31701,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -31450,8 +32668,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -31815,7 +33033,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -32146,8 +33364,9 @@ spec: variable present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -32206,6 +33425,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume + mount containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -32269,8 +33525,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -32297,9 +33553,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the - name of each environment variable. Must - be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -32986,7 +34242,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -33041,10 +34297,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -33056,6 +34312,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how + a container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to + check on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -34159,15 +35468,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -34777,8 +36084,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched @@ -35171,7 +36478,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35283,7 +36590,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35348,7 +36655,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -35642,6 +36949,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -36494,8 +37906,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -37077,6 +38489,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be addressed + to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -37446,15 +38963,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -37481,7 +38996,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -38166,8 +39681,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -38553,7 +40068,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -39136,7 +40651,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -39773,8 +41288,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -40164,8 +41679,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -40219,6 +41735,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -40276,8 +41829,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -40300,8 +41853,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -40970,7 +42524,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -41025,10 +42579,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -41040,6 +42594,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -41723,15 +43330,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -41753,8 +43358,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must be - a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -41812,6 +43418,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -41891,8 +43534,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each - environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -42124,7 +43768,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -42224,8 +43868,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -42283,6 +43928,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -42344,8 +44026,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -42372,8 +44054,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -43050,7 +44733,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -43105,10 +44788,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -43120,6 +44803,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -43669,7 +45405,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -43968,7 +45704,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -44212,15 +45948,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -44715,15 +46449,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -45007,6 +46739,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -45166,7 +47003,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -45910,8 +47747,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -46516,6 +48353,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -46661,8 +48603,9 @@ spec: present in a Container. properties: name: - description: Name of the environment variable. - Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -46717,6 +48660,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount + containing the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -46775,8 +48755,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -46799,8 +48779,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name - of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -47471,7 +49452,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -47526,10 +49507,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -47541,6 +49522,59 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a + container exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check + on container exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -48105,8 +50139,9 @@ spec: in a Container. properties: name: - description: Name of the environment variable. Must - be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -48164,6 +50199,43 @@ spec: - fieldPath type: object x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -48243,8 +50315,9 @@ spec: type: object x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of - each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -48327,7 +50400,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -48686,7 +50759,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -49716,8 +51789,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. items: description: The weights of all of the matched WeightedPodAffinityTerm @@ -50306,6 +52379,111 @@ spec: type: array x-kubernetes-list-type: atomic type: object + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + format: int32 + type: integer + signerName: + description: Kubelet's generated CSRs will be + addressed to this signer. + type: string + required: + - keyType + - signerName + type: object secret: description: secret information about the secret data to project @@ -50599,15 +52777,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -50662,7 +52838,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. diff --git a/go.mod b/go.mod index a62c370056..5ff4923f4f 100644 --- a/go.mod +++ b/go.mod @@ -34,9 +34,9 @@ require ( golang.org/x/crypto v0.41.0 google.golang.org/grpc v1.74.2 gotest.tools/v3 v3.5.2 - k8s.io/api v0.33.4 - k8s.io/apimachinery v0.33.4 - k8s.io/client-go v0.33.4 + k8s.io/api v0.34.1 + k8s.io/apimachinery v0.34.1 + k8s.io/client-go v0.34.1 k8s.io/component-base v0.33.4 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.6.0 @@ -47,7 +47,7 @@ require ( github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/btree v1.1.3 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect @@ -57,9 +57,11 @@ require ( go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/mod v0.27.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) require ( @@ -70,7 +72,7 @@ require ( github.com/bool64/shared v0.1.5 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect @@ -82,7 +84,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/gnostic-models v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 github.com/iancoleman/orderedmap v0.3.0 // indirect @@ -93,7 +95,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -105,7 +107,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/sergi/go-diff v1.3.1 // indirect github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/testify v1.10.0 github.com/swaggest/assertjson v1.9.0 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect @@ -132,8 +134,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.33.4 k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect - k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 - sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect + k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect + k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect ) diff --git a/go.sum b/go.sum index beab94c835..c71d78ebaf 100644 --- a/go.sum +++ b/go.sum @@ -24,8 +24,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= @@ -34,8 +34,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= +github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -74,10 +74,9 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= -github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= +github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= +github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -133,8 +132,9 @@ github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVO github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= @@ -178,8 +178,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= @@ -245,8 +245,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= -go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= -go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -338,31 +338,29 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk= -k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc= +k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= +k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= k8s.io/apiextensions-apiserver v0.33.4 h1:rtq5SeXiDbXmSwxsF0MLe2Mtv3SwprA6wp+5qh/CrOU= k8s.io/apiextensions-apiserver v0.33.4/go.mod h1:mWXcZQkQV1GQyxeIjYApuqsn/081hhXPZwZ2URuJeSs= -k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s= -k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM= -k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw= -k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY= +k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= +k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= +k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= k8s.io/component-base v0.33.4 h1:Jvb/aw/tl3pfgnJ0E0qPuYLT0NwdYs1VXXYQmSuxJGY= k8s.io/component-base v0.33.4/go.mod h1:567TeSdixWW2Xb1yYUQ7qk5Docp2kNznKL87eygY8Rc= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= -k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= -k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= +k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= +k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= -sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= -sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= -sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= +sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/internal/controller/pgupgrade/jobs_test.go b/internal/controller/pgupgrade/jobs_test.go index eb3a45d414..737f023ce7 100644 --- a/internal/controller/pgupgrade/jobs_test.go +++ b/internal/controller/pgupgrade/jobs_test.go @@ -138,7 +138,6 @@ kind: Job metadata: annotations: kubectl.kubernetes.io/default-container: database - creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 postgres-operator.crunchydata.com/pgupgrade: pgu2 @@ -159,7 +158,6 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: database - creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 postgres-operator.crunchydata.com/pgupgrade: pgu2 @@ -283,7 +281,6 @@ kind: Job metadata: annotations: kubectl.kubernetes.io/default-container: database - creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 postgres-operator.crunchydata.com/pgupgrade: pgu2 @@ -303,7 +300,6 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: database - creationTimestamp: null labels: postgres-operator.crunchydata.com/cluster: pg5 postgres-operator.crunchydata.com/pgupgrade: pgu2 diff --git a/internal/controller/postgrescluster/cluster_test.go b/internal/controller/postgrescluster/cluster_test.go index dbfd7de93b..5186bda145 100644 --- a/internal/controller/postgrescluster/cluster_test.go +++ b/internal/controller/postgrescluster/cluster_test.go @@ -603,7 +603,6 @@ apiVersion: v1 kind: Service `)) assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` -creationTimestamp: null labels: app.kubernetes.io/component: pg app.kubernetes.io/instance: pg5 @@ -637,7 +636,6 @@ ownerReferences: apiVersion: v1 kind: Endpoints metadata: - creationTimestamp: null labels: app.kubernetes.io/component: pg app.kubernetes.io/instance: pg5 @@ -737,7 +735,6 @@ apiVersion: v1 kind: Service `)) assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` -creationTimestamp: null labels: app.kubernetes.io/component: pg app.kubernetes.io/instance: pg2 diff --git a/internal/controller/postgrescluster/patroni_test.go b/internal/controller/postgrescluster/patroni_test.go index b887d8c3b5..3892e2dacd 100644 --- a/internal/controller/postgrescluster/patroni_test.go +++ b/internal/controller/postgrescluster/patroni_test.go @@ -55,7 +55,6 @@ apiVersion: v1 kind: Service `)) assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` -creationTimestamp: null labels: app.kubernetes.io/instance: pg2 app.kubernetes.io/managed-by: percona-postgresql-operator diff --git a/internal/controller/postgrescluster/pgadmin_test.go b/internal/controller/postgrescluster/pgadmin_test.go index c1bead1f04..62b7be81e7 100644 --- a/internal/controller/postgrescluster/pgadmin_test.go +++ b/internal/controller/postgrescluster/pgadmin_test.go @@ -74,7 +74,6 @@ apiVersion: v1 kind: ConfigMap `)) assert.Assert(t, cmp.MarshalMatches(configmap.ObjectMeta, ` -creationTimestamp: null labels: app.kubernetes.io/instance: pg1 app.kubernetes.io/managed-by: percona-postgresql-operator @@ -154,7 +153,6 @@ func TestGeneratePGAdminService(t *testing.T) { assert.Assert(t, !specified) assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` -creationTimestamp: null name: my-cluster-pgadmin namespace: my-ns `)) @@ -171,7 +169,6 @@ apiVersion: v1 kind: Service `)) assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` -creationTimestamp: null labels: app.kubernetes.io/instance: my-cluster app.kubernetes.io/managed-by: percona-postgresql-operator @@ -522,7 +519,6 @@ func TestReconcilePGAdminStatefulSet(t *testing.T) { assert.Assert(t, cmp.MarshalMatches(template.ObjectMeta, ` annotations: kubectl.kubernetes.io/default-container: pgadmin -creationTimestamp: null labels: app.kubernetes.io/instance: test-cluster app.kubernetes.io/managed-by: percona-postgresql-operator @@ -643,7 +639,6 @@ terminationGracePeriodSeconds: 30 annotations: annotation1: annotationvalue kubectl.kubernetes.io/default-container: pgadmin -creationTimestamp: null labels: app.kubernetes.io/instance: custom-cluster app.kubernetes.io/managed-by: percona-postgresql-operator diff --git a/internal/controller/postgrescluster/pgbouncer_test.go b/internal/controller/postgrescluster/pgbouncer_test.go index 82c152b857..9424604f70 100644 --- a/internal/controller/postgrescluster/pgbouncer_test.go +++ b/internal/controller/postgrescluster/pgbouncer_test.go @@ -55,7 +55,6 @@ func TestGeneratePGBouncerService(t *testing.T) { assert.Assert(t, !specified) assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` -creationTimestamp: null name: pg7-pgbouncer namespace: ns5 `)) @@ -74,7 +73,6 @@ apiVersion: v1 kind: Service `)) assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` -creationTimestamp: null labels: app.kubernetes.io/component: pgbouncer app.kubernetes.io/instance: pg7 @@ -399,7 +397,6 @@ func TestGeneratePGBouncerDeployment(t *testing.T) { assert.Assert(t, !specified) assert.Assert(t, cmp.MarshalMatches(deploy.ObjectMeta, ` -creationTimestamp: null name: test-cluster-pgbouncer namespace: ns3 `)) diff --git a/internal/controller/standalone_pgadmin/configmap_test.go b/internal/controller/standalone_pgadmin/configmap_test.go index f895d56362..3c0fd7eb2d 100644 --- a/internal/controller/standalone_pgadmin/configmap_test.go +++ b/internal/controller/standalone_pgadmin/configmap_test.go @@ -175,7 +175,6 @@ apiVersion: v1 kind: ConfigMap `)) assert.Assert(t, cmp.MarshalMatches(configmap.ObjectMeta, ` -creationTimestamp: null labels: postgres-operator.crunchydata.com/pgadmin: pg1 postgres-operator.crunchydata.com/role: pgadmin diff --git a/internal/controller/standalone_pgadmin/service_test.go b/internal/controller/standalone_pgadmin/service_test.go index a5fed9791a..d385b6dbc5 100644 --- a/internal/controller/standalone_pgadmin/service_test.go +++ b/internal/controller/standalone_pgadmin/service_test.go @@ -39,7 +39,6 @@ kind: Service assert.Assert(t, cmp.MarshalMatches(service.ObjectMeta, ` annotations: test-annotation: test-annotation-val -creationTimestamp: null labels: postgres-operator.crunchydata.com/pgadmin: daisy postgres-operator.crunchydata.com/role: pgadmin diff --git a/internal/controller/standalone_pgadmin/statefulset_test.go b/internal/controller/standalone_pgadmin/statefulset_test.go index 1ddd967ede..5326366771 100644 --- a/internal/controller/standalone_pgadmin/statefulset_test.go +++ b/internal/controller/standalone_pgadmin/statefulset_test.go @@ -75,7 +75,6 @@ func TestReconcilePGAdminStatefulSet(t *testing.T) { assert.Assert(t, cmp.MarshalMatches(template.ObjectMeta, ` annotations: kubectl.kubernetes.io/default-container: pgadmin -creationTimestamp: null labels: postgres-operator.crunchydata.com/data: pgadmin postgres-operator.crunchydata.com/pgadmin: test-standalone-pgadmin @@ -173,7 +172,6 @@ terminationGracePeriodSeconds: 30 annotations: annotation1: annotationvalue kubectl.kubernetes.io/default-container: pgadmin -creationTimestamp: null labels: label1: labelvalue postgres-operator.crunchydata.com/data: pgadmin diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go index dec503f43c..8a904258a8 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go @@ -40,8 +40,7 @@ func TestPostgresClusterDefault(t *testing.T) { assert.DeepEqual(t, string(b), strings.TrimSpace(` apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster -metadata: - creationTimestamp: null +metadata: {} spec: backups: pgbackrest: {} @@ -74,8 +73,7 @@ status: assert.DeepEqual(t, string(b), strings.TrimSpace(` apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster -metadata: - creationTimestamp: null +metadata: {} spec: backups: pgbackrest: {} From c0a3088264c7598cb6b023d34b374a9f180bd011 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 25 Sep 2025 19:13:54 +0300 Subject: [PATCH 142/300] K8SPG-757: fix version check (#1287) https://perconadev.atlassian.net/browse/K8SPG-757 Co-authored-by: Viacheslav Sarzhan --- percona/controller/pgcluster/controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index c9b8f7ba0c..48e65eae35 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -442,7 +442,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, "-c", "sleep 60", }, Resources: cr.Spec.InstanceSets[0].Resources, - SecurityContext: initialize.RestrictedSecurityContext(cr.CompareVersion("2.5.0") >= 0), + SecurityContext: initialize.RestrictedSecurityContext(cr.CompareVersion("2.8.0") >= 0), }, }, SecurityContext: cr.Spec.InstanceSets[0].SecurityContext, From ef9e2107792b0a7b8c8deceb1dace71d9ad9dc83 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 25 Sep 2025 18:17:37 +0200 Subject: [PATCH 143/300] K8SPG-748 fix statuses (#1285) Co-authored-by: Viacheslav Sarzhan --- percona/controller/pgcluster/status.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index 28fa3d7148..2589a26e35 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -146,6 +146,12 @@ func updateConditions(cr *v2.PerconaPGCluster, status *v1beta1.PostgresClusterSt } } + syncConditionsFromPostgresToPercona(cr, status) + + syncPatroniFromPostgresToPercona(cr, status) + + syncPgbackrestFromPostgresToPercona(cr, status) + repoCondition := meta.FindStatusCondition(status.Conditions, postgrescluster.ConditionRepoHostReady) if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { setClusterNotReadyCondition(metav1.ConditionFalse, postgrescluster.ConditionRepoHostReady) @@ -160,12 +166,6 @@ func updateConditions(cr *v2.PerconaPGCluster, status *v1beta1.PostgresClusterSt setClusterNotReadyCondition(metav1.ConditionTrue, "AllConditionsAreTrue") - syncConditionsFromPostgresToPercona(cr, status) - - syncPatroniFromPostgresToPercona(cr, status) - - syncPgbackrestFromPostgresToPercona(cr, status) - } func syncConditionsFromPostgresToPercona(cr *v2.PerconaPGCluster, postgresStatus *v1beta1.PostgresClusterStatus) { From ab6c6dd559ad49d96d732c0ea5d419aecf3ffa80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:36:30 +0300 Subject: [PATCH 144/300] CLOUD-727: Bump google.golang.org/grpc from 1.74.2 to 1.75.1 (#1280) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.74.2 to 1.75.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.74.2...v1.75.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.75.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 6 +++--- go.sum | 14 ++++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 5ff4923f4f..af1551655f 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( go.opentelemetry.io/otel/trace v1.37.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.41.0 - google.golang.org/grpc v1.74.2 + google.golang.org/grpc v1.75.1 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.1 k8s.io/apimachinery v0.34.1 @@ -127,8 +127,8 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.36.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect google.golang.org/protobuf v1.36.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index c71d78ebaf..60d6d1c01e 100644 --- a/go.sum +++ b/go.sum @@ -309,12 +309,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= -google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= From e7e246bf199ba6ebc2de40090e9557af17e973dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:41:31 +0300 Subject: [PATCH 145/300] CLOUD-727: Bump github.com/onsi/gomega from 1.38.0 to 1.38.2 (#1276) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.38.0 to 1.38.2. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.38.0...v1.38.2) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-version: 1.38.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index af1551655f..cbc0cc287d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 github.com/onsi/ginkgo/v2 v2.25.1 - github.com/onsi/gomega v1.38.0 + github.com/onsi/gomega v1.38.2 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 @@ -43,7 +43,7 @@ require ( ) require ( - github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect diff --git a/go.sum b/go.sum index 60d6d1c01e..008f740eae 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= -github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc h1:aBpUepmWt8NsLH0fOA6vb8CCvIIJ4jMNxpvR36PaRSs= github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc/go.mod h1:dOzRkbUNd/qpn35nOSy60ZQBiP9wa9g1kh9kaMg/tOk= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -147,8 +147,8 @@ github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY= github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= -github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= -github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= From 0b8ba07ae3a4912793bdf7e61f8347e261c2371e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:44:41 +0300 Subject: [PATCH 146/300] CLOUD-727: Bump go.opentelemetry.io/otel/trace from 1.37.0 to 1.38.0 (#1275) Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.37.0 to 1.38.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.37.0...v1.38.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/trace dependency-version: 1.38.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index cbc0cc287d..da8b198298 100644 --- a/go.mod +++ b/go.mod @@ -24,12 +24,12 @@ require ( github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.32.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 - go.opentelemetry.io/otel v1.37.0 + go.opentelemetry.io/otel v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 go.opentelemetry.io/otel/sdk v1.37.0 - go.opentelemetry.io/otel/trace v1.37.0 + go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.41.0 google.golang.org/grpc v1.75.1 @@ -108,14 +108,14 @@ require ( github.com/sergi/go-diff v1.3.1 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/pflag v1.0.6 // indirect - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 github.com/swaggest/assertjson v1.9.0 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect - go.opentelemetry.io/otel/metric v1.37.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.43.0 // indirect diff --git a/go.sum b/go.sum index 008f740eae..47861a09c9 100644 --- a/go.sum +++ b/go.sum @@ -186,8 +186,8 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= @@ -217,22 +217,22 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4= -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= From eed74ec41e833da9d99c0d398b1fa709f3b9a22b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:46:57 +0300 Subject: [PATCH 147/300] CLOUD-727: Bump github.com/go-openapi/swag from 0.23.1 to 0.24.1 (#1273) Bumps [github.com/go-openapi/swag](https://github.com/go-openapi/swag) from 0.23.1 to 0.24.1. - [Commits](https://github.com/go-openapi/swag/compare/v0.23.1...v0.24.1) --- updated-dependencies: - dependency-name: github.com/go-openapi/swag dependency-version: 0.24.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 15 ++++++++++++--- go.sum | 32 ++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index da8b198298..b68ea7d3fe 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-openapi/errors v0.22.2 github.com/go-openapi/runtime v0.28.0 github.com/go-openapi/strfmt v0.23.0 - github.com/go-openapi/swag v0.23.1 + github.com/go-openapi/swag v0.25.0 github.com/go-openapi/validate v0.24.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 @@ -48,6 +48,17 @@ require ( github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/go-openapi/swag/cmdutils v0.25.0 // indirect + github.com/go-openapi/swag/conv v0.25.0 // indirect + github.com/go-openapi/swag/fileutils v0.25.0 // indirect + github.com/go-openapi/swag/jsonname v0.25.0 // indirect + github.com/go-openapi/swag/jsonutils v0.25.0 // indirect + github.com/go-openapi/swag/loading v0.25.0 // indirect + github.com/go-openapi/swag/mangling v0.25.0 // indirect + github.com/go-openapi/swag/netutils v0.25.0 // indirect + github.com/go-openapi/swag/stringutils v0.25.0 // indirect + github.com/go-openapi/swag/typeutils v0.25.0 // indirect + github.com/go-openapi/swag/yamlutils v0.25.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/btree v1.1.3 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect @@ -89,9 +100,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.9.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect diff --git a/go.sum b/go.sum index 47861a09c9..d4169d6b52 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,32 @@ github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9Z github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= -github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= -github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= +github.com/go-openapi/swag v0.25.0 h1:xyZhlgInBg6wOtyTD5b+pzwVqHSOliAvgvKW+POFUts= +github.com/go-openapi/swag v0.25.0/go.mod h1:yhsa7GJvO1JBFZccLq9uh/MawsC0PQd8sNz88VBXQlU= +github.com/go-openapi/swag/cmdutils v0.25.0 h1:iYZ24DEGPEk6L1jO09vw39KfpxbG7KhS+WeQexS8U5A= +github.com/go-openapi/swag/cmdutils v0.25.0/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.0 h1:5K+e44HkOgCVE0IJTbivurzHahT62DPr2DEJqR/+4pA= +github.com/go-openapi/swag/conv v0.25.0/go.mod h1:oa1ZZnb1jubNdZlD1iAhGXt6Ic4hHtuO23MwTgAXR88= +github.com/go-openapi/swag/fileutils v0.25.0 h1:t7aQRuRfsP29dY4vfrNvDZv7RurwRHuyjUedtYVDmYY= +github.com/go-openapi/swag/fileutils v0.25.0/go.mod h1:+NXtt5xNZZqmpIpjqcujqojGFek9/w55b3ecmOdtg8M= +github.com/go-openapi/swag/jsonname v0.25.0 h1:+fuNs9gdkb2w10hgsgOBx9jtx0pvtUaDRYxD91BEpEQ= +github.com/go-openapi/swag/jsonname v0.25.0/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= +github.com/go-openapi/swag/jsonutils v0.25.0 h1:ELKpJT29T4N/AvmDqMeDFLx2QRZQOYFthzctbIX30+A= +github.com/go-openapi/swag/jsonutils v0.25.0/go.mod h1:KYL8GyGoi6tek9ajpvn0le4BWmKoUVVv8yPxklViIMo= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.0 h1:ca9vKxLnJegL2bzqXRWNabKdqVGxBzrnO8/UZnr5W0Y= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.0/go.mod h1:kjmweouyPwRUEYMSrbAidoLMGeJ5p6zdHi9BgZiqmsg= +github.com/go-openapi/swag/loading v0.25.0 h1:e9mjE5fJeaK0LTepHMtG0Ief+9ETXLFhWCx7ZfiI6LI= +github.com/go-openapi/swag/loading v0.25.0/go.mod h1:2ZCWXwVY1XYuoue8Bdjbn5GJK4/ufXbCfcvoSPFQJqM= +github.com/go-openapi/swag/mangling v0.25.0 h1:VdTfDWX5lS3yURxYHF5SK7kYelSK69Lv2xEAeudTzM8= +github.com/go-openapi/swag/mangling v0.25.0/go.mod h1:CdiMQ6pnfAgyQGSOIYnZkXvqhnnwOn997uXZMAd/7mQ= +github.com/go-openapi/swag/netutils v0.25.0 h1:/e1LPmXfF9fcOYbbaP3+SQgon1fRwe5EZ0FjpR4vAjs= +github.com/go-openapi/swag/netutils v0.25.0/go.mod h1:CAkkvqnUJX8NV96tNhEQvKz8SQo2KF0f7LleiJwIeRE= +github.com/go-openapi/swag/stringutils v0.25.0 h1:iYfCF45GUeI/1Yrh8rQtTFCp5K1ToqWhUdzJZwvXvv8= +github.com/go-openapi/swag/stringutils v0.25.0/go.mod h1:JLdSAq5169HaiDUbTvArA2yQxmgn4D6h4A+4HqVvAYg= +github.com/go-openapi/swag/typeutils v0.25.0 h1:iUTsxu3F3h9v6CBzVFGXKPSBQt6d8XXgYy1YAlu+HJ8= +github.com/go-openapi/swag/typeutils v0.25.0/go.mod h1:9McMC/oCdS4BKwk2shEB7x17P6HmMmA6dQRtAkSnNb8= +github.com/go-openapi/swag/yamlutils v0.25.0 h1:apgy77seWLEM9HKDcieIgW8bG9aSZgH6nQ9THlHYgHA= +github.com/go-openapi/swag/yamlutils v0.25.0/go.mod h1:0JvBRtc0mR02IqHURUeGgS9cG+Dfms4FCGXCnsgnt7c= github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= @@ -100,8 +124,6 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -119,8 +141,6 @@ github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 h1:Q3jQ1NkFqv5o+ github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= From 2eefb3944917fbc82c2f21bb90480fc46c9e188d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 20:57:20 +0300 Subject: [PATCH 148/300] CLOUD-727: Bump github.com/grpc-ecosystem/grpc-gateway/v2 (#1262) Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.27.1 to 2.27.2. - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.27.1...v2.27.2) --- updated-dependencies: - dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2 dependency-version: 2.27.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index b68ea7d3fe..3fc261f9e0 100644 --- a/go.mod +++ b/go.mod @@ -97,7 +97,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -136,8 +136,8 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.36.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect google.golang.org/protobuf v1.36.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index d4169d6b52..a746e80b01 100644 --- a/go.sum +++ b/go.sum @@ -114,8 +114,8 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= @@ -331,10 +331,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= From 83ddc30cc503e02e0e32e2fb66369ad94a9b14e6 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 26 Sep 2025 09:35:32 +0300 Subject: [PATCH 149/300] CLOUD-727 Bump golang 1251 (#1286) Co-authored-by: Viacheslav Sarzhan --- .github/linters/go.mod | 2 +- .github/workflows/reviewdog.yml | 6 +++--- .github/workflows/test.yml | 2 +- Jenkinsfile | 2 +- build/postgres-operator/Dockerfile | 2 +- go.mod | 4 +--- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/linters/go.mod b/.github/linters/go.mod index 4cbfd91f14..b652c5cf47 100644 --- a/.github/linters/go.mod +++ b/.github/linters/go.mod @@ -1,3 +1,3 @@ module linters -go 1.23.4 +go 1.25.1 diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 7df94fb822..14622c62d7 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '^1.23' + go-version: '^1.25.1' - uses: actions/checkout@v5 - name: golangci-lint uses: golangci/golangci-lint-action@v8 @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: - go-version: '^1.23' + go-version: '^1.25.1' - run: go install -v github.com/incu6us/goimports-reviser/v3@latest - run: $(go env GOPATH)/bin/goimports-reviser -imports-order "std,general,company,project" -company-prefixes "github.com/percona" ./... - uses: reviewdog/action-suggester@v1 @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: - go-version: '^1.23' + go-version: '^1.25.1' - run: go install mvdan.cc/sh/v3/cmd/shfmt@latest - run: $(go env GOPATH)/bin/shfmt -bn -ci -s -w . - name: suggester / shfmt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e9ced8ecb8..42a332a320 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: '^1.23' + go-version: '^1.25.1' - uses: actions/checkout@v5 - name: Basic tests run: make check diff --git a/Jenkinsfile b/Jenkinsfile index 4bc55e5862..a56d6b214f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -496,7 +496,7 @@ pipeline { -v $WORKSPACE/src/github.com/percona/percona-postgresql-operator:/go/src/github.com/percona/percona-postgresql-operator \ -w /go/src/github.com/percona/percona-postgresql-operator \ -e GO111MODULE=on \ - golang:1.24 sh -c ' + golang:1.25.1 sh -c ' go install github.com/google/go-licenses@latest; /go/bin/go-licenses csv github.com/percona/percona-postgresql-operator/cmd/postgres-operator \ | cut -d , -f 3 \ diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index f39296f8a1..06003a05e9 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=${BUILDPLATFORM} golang:1.24 AS go_builder +FROM --platform=${BUILDPLATFORM} golang:1.25 AS go_builder WORKDIR /go/src/github.com/percona/percona-postgresql-operator COPY go.mod go.sum ./ diff --git a/go.mod b/go.mod index 3fc261f9e0..28438fa029 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/percona/percona-postgresql-operator -go 1.24.0 - -toolchain go1.24.1 +go 1.25.1 require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc From d44a9260957cc6c5df76301458d2c4b5002ee34e Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Mon, 29 Sep 2025 13:01:28 +0300 Subject: [PATCH 150/300] K8SPG-611: official postgres image support (#1212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * K8SPG-611: official postgres image support https://perconadev.atlassian.net/browse/K8SPG-611 * fix custom-extensions test * fix init-deploy test * all tests passed reverting version changes * revert image changes * fix merge * fix custom-extensions test * fix test * use official image in tests --------- Co-authored-by: Natalia Marukovich Co-authored-by: Ege Güneş --- build/postgres-operator/Dockerfile | 1 + build/postgres-operator/init-entrypoint.sh | 1 + .../postgres-operator/relocate-extensions.sh | 14 +++++++++ .../tests/custom-extensions/02-assert.yaml | 8 +++-- .../tests/custom-extensions/05-assert.yaml | 8 +++-- .../tests/custom-extensions/06-assert.yaml | 10 ++++--- .../tests/custom-extensions/07-assert.yaml | 6 ++-- .../tests/custom-extensions/11-assert.yaml | 12 ++------ .../tests/custom-extensions/14-assert.yaml | 12 ++------ .../tests/custom-extensions/15-assert.yaml | 12 ++------ .../01-create-cluster.yaml | 4 +-- .../upgrade-consistency/02-patch-cluster.yaml | 1 + .../upgrade-consistency/03-patch-cluster.yaml | 1 - e2e-tests/vars.sh | 2 +- internal/patroni/reconcile.go | 12 ++++++-- percona/extensions/containers.go | 29 ++++++++++++++----- 16 files changed, 78 insertions(+), 55 deletions(-) create mode 100755 build/postgres-operator/relocate-extensions.sh diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index 06003a05e9..6757f90686 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -62,6 +62,7 @@ COPY --from=go_builder /usr/local/bin/extension-installer /usr/local/bin COPY --from=go_builder /usr/local/bin/pgbackrest /usr/local/bin/ COPY --from=go_builder /licenses /licenses COPY build/postgres-operator/install-extensions.sh /usr/local/bin +COPY build/postgres-operator/relocate-extensions.sh /usr/local/bin COPY build/postgres-operator/init-entrypoint.sh /usr/local/bin COPY build/postgres-operator/postgres-entrypoint.sh /usr/local/bin COPY build/postgres-operator/postgres-liveness-check.sh /usr/local/bin diff --git a/build/postgres-operator/init-entrypoint.sh b/build/postgres-operator/init-entrypoint.sh index 533b78a84d..2fde1f02bf 100755 --- a/build/postgres-operator/init-entrypoint.sh +++ b/build/postgres-operator/init-entrypoint.sh @@ -9,3 +9,4 @@ install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/pgbackrest" "${CR install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-entrypoint.sh" "${CRUNCHY_BINDIR}/bin/postgres-entrypoint.sh" install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-liveness-check.sh" "${CRUNCHY_BINDIR}/bin/postgres-liveness-check.sh" install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-readiness-check.sh" "${CRUNCHY_BINDIR}/bin/postgres-readiness-check.sh" +install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/relocate-extensions.sh" "${CRUNCHY_BINDIR}/bin/relocate-extensions.sh" diff --git a/build/postgres-operator/relocate-extensions.sh b/build/postgres-operator/relocate-extensions.sh new file mode 100755 index 0000000000..ca786b745f --- /dev/null +++ b/build/postgres-operator/relocate-extensions.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +PG_EXTENSIONS_DIR=/usr/pgsql-${PG_VERSION}/share/extension +PG_LIB_DIR=/usr/pgsql-${PG_VERSION}/lib + +PGDATA_EXTENSIONS_DIR=/pgdata/extension/${PG_VERSION}/usr/pgsql-${PG_VERSION}/share/extension +PGDATA_LIB_DIR=/pgdata/extension/${PG_VERSION}/usr/pgsql-${PG_VERSION}/lib + +mkdir -p "${PGDATA_EXTENSIONS_DIR}" +mkdir -p "${PGDATA_LIB_DIR}" + +cp -r "${PG_EXTENSIONS_DIR}"/* "${PGDATA_EXTENSIONS_DIR}/" +cp -r "${PG_LIB_DIR}"/* "${PGDATA_LIB_DIR}/" diff --git a/e2e-tests/tests/custom-extensions/02-assert.yaml b/e2e-tests/tests/custom-extensions/02-assert.yaml index ae1514543e..2a5fe7284e 100644 --- a/e2e-tests/tests/custom-extensions/02-assert.yaml +++ b/e2e-tests/tests/custom-extensions/02-assert.yaml @@ -19,13 +19,17 @@ spec: template: spec: initContainers: + - command: + - /usr/local/bin/init-entrypoint.sh - name: postgres-startup - command: - - /usr/local/bin/relocate-extensions.sh + - /opt/crunchy/bin/relocate-extensions.sh resources: {} volumeMounts: - mountPath: /pgdata name: postgres-data + - mountPath: /opt/crunchy + name: crunchy-bin - mountPath: /tmp name: tmp - command: @@ -56,8 +60,6 @@ spec: - name: postgres-data - mountPath: /tmp name: tmp - - command: - - /usr/local/bin/init-entrypoint.sh - name: nss-wrapper-init status: observedGeneration: 2 diff --git a/e2e-tests/tests/custom-extensions/05-assert.yaml b/e2e-tests/tests/custom-extensions/05-assert.yaml index ae1514543e..2a5fe7284e 100644 --- a/e2e-tests/tests/custom-extensions/05-assert.yaml +++ b/e2e-tests/tests/custom-extensions/05-assert.yaml @@ -19,13 +19,17 @@ spec: template: spec: initContainers: + - command: + - /usr/local/bin/init-entrypoint.sh - name: postgres-startup - command: - - /usr/local/bin/relocate-extensions.sh + - /opt/crunchy/bin/relocate-extensions.sh resources: {} volumeMounts: - mountPath: /pgdata name: postgres-data + - mountPath: /opt/crunchy + name: crunchy-bin - mountPath: /tmp name: tmp - command: @@ -56,8 +60,6 @@ spec: - name: postgres-data - mountPath: /tmp name: tmp - - command: - - /usr/local/bin/init-entrypoint.sh - name: nss-wrapper-init status: observedGeneration: 2 diff --git a/e2e-tests/tests/custom-extensions/06-assert.yaml b/e2e-tests/tests/custom-extensions/06-assert.yaml index 9e0e8c2d25..1429f26062 100644 --- a/e2e-tests/tests/custom-extensions/06-assert.yaml +++ b/e2e-tests/tests/custom-extensions/06-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 180 +timeout: 240 --- kind: StatefulSet apiVersion: apps/v1 @@ -19,15 +19,19 @@ spec: template: spec: initContainers: + - command: + - /usr/local/bin/init-entrypoint.sh - name: postgres-startup - command: - - /usr/local/bin/relocate-extensions.sh + - /opt/crunchy/bin/relocate-extensions.sh env: - name: PG_VERSION resources: {} volumeMounts: - mountPath: /pgdata name: postgres-data + - mountPath: /opt/crunchy + name: crunchy-bin - mountPath: /tmp name: tmp - command: @@ -58,8 +62,6 @@ spec: - name: postgres-data - mountPath: /tmp name: tmp - - command: - - /usr/local/bin/init-entrypoint.sh - name: nss-wrapper-init status: observedGeneration: 3 diff --git a/e2e-tests/tests/custom-extensions/07-assert.yaml b/e2e-tests/tests/custom-extensions/07-assert.yaml index 9918171314..366a3c08a2 100644 --- a/e2e-tests/tests/custom-extensions/07-assert.yaml +++ b/e2e-tests/tests/custom-extensions/07-assert.yaml @@ -19,13 +19,13 @@ spec: template: spec: initContainers: + - command: + - /usr/local/bin/init-entrypoint.sh - name: postgres-startup - command: - - /usr/local/bin/relocate-extensions.sh + - /opt/crunchy/bin/relocate-extensions.sh - command: - /usr/local/bin/install-extensions.sh - - command: - - /usr/local/bin/init-entrypoint.sh - name: nss-wrapper-init status: observedGeneration: 3 diff --git a/e2e-tests/tests/custom-extensions/11-assert.yaml b/e2e-tests/tests/custom-extensions/11-assert.yaml index 9e347dd025..ff07dc24e2 100644 --- a/e2e-tests/tests/custom-extensions/11-assert.yaml +++ b/e2e-tests/tests/custom-extensions/11-assert.yaml @@ -19,15 +19,11 @@ spec: template: spec: initContainers: + - command: + - /usr/local/bin/init-entrypoint.sh - name: postgres-startup - command: - - /usr/local/bin/relocate-extensions.sh - resources: {} - volumeMounts: - - mountPath: /pgdata - name: postgres-data - - mountPath: /tmp - name: tmp + - /opt/crunchy/bin/relocate-extensions.sh - command: - /usr/local/bin/install-extensions.sh env: @@ -52,8 +48,6 @@ spec: - name: postgres-data - mountPath: /tmp name: tmp - - command: - - /usr/local/bin/init-entrypoint.sh - name: nss-wrapper-init status: observedGeneration: 5 diff --git a/e2e-tests/tests/custom-extensions/14-assert.yaml b/e2e-tests/tests/custom-extensions/14-assert.yaml index 9e347dd025..ff07dc24e2 100644 --- a/e2e-tests/tests/custom-extensions/14-assert.yaml +++ b/e2e-tests/tests/custom-extensions/14-assert.yaml @@ -19,15 +19,11 @@ spec: template: spec: initContainers: + - command: + - /usr/local/bin/init-entrypoint.sh - name: postgres-startup - command: - - /usr/local/bin/relocate-extensions.sh - resources: {} - volumeMounts: - - mountPath: /pgdata - name: postgres-data - - mountPath: /tmp - name: tmp + - /opt/crunchy/bin/relocate-extensions.sh - command: - /usr/local/bin/install-extensions.sh env: @@ -52,8 +48,6 @@ spec: - name: postgres-data - mountPath: /tmp name: tmp - - command: - - /usr/local/bin/init-entrypoint.sh - name: nss-wrapper-init status: observedGeneration: 5 diff --git a/e2e-tests/tests/custom-extensions/15-assert.yaml b/e2e-tests/tests/custom-extensions/15-assert.yaml index 6798d2dc4f..ed11482f24 100644 --- a/e2e-tests/tests/custom-extensions/15-assert.yaml +++ b/e2e-tests/tests/custom-extensions/15-assert.yaml @@ -19,15 +19,11 @@ spec: template: spec: initContainers: + - command: + - /usr/local/bin/init-entrypoint.sh - name: postgres-startup - command: - - /usr/local/bin/relocate-extensions.sh - resources: {} - volumeMounts: - - mountPath: /pgdata - name: postgres-data - - mountPath: /tmp - name: tmp + - /opt/crunchy/bin/relocate-extensions.sh - command: - /usr/local/bin/install-extensions.sh env: @@ -52,8 +48,6 @@ spec: - name: postgres-data - mountPath: /tmp name: tmp - - command: - - /usr/local/bin/init-entrypoint.sh - name: nss-wrapper-init status: observedGeneration: 6 diff --git a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml index f7446f8210..086564ae21 100644 --- a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml @@ -9,7 +9,7 @@ commands: source ../../functions get_cr \ - | yq eval ' - .spec.crVersion="2.6.0"' - \ + | yq eval '.spec.crVersion="2.6.0"' - \ + | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:main-ppg$PG_VER-pgbackrest\"" - \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index 2d3cb25d26..1caf07a01d 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -11,6 +11,7 @@ commands: get_cr \ | yq eval ' .spec.crVersion="2.7.0"' - \ + | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index ea48c5a48d..8ce02b3f72 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -11,7 +11,6 @@ commands: get_cr \ | yq eval ' .spec.crVersion="2.8.0"' - \ - | yq eval ".spec.backups.pgbackrest.image=\"$IMAGE_BACKREST\"" - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 185eeda8e9..501072d19b 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -25,7 +25,7 @@ export IMAGE_BASE=${IMAGE_BASE:-"perconalab/percona-postgresql-operator"} export IMAGE=${IMAGE:-"${IMAGE_BASE}:${VERSION}"} export PG_VER="${PG_VER:-17}" export IMAGE_PGBOUNCER=${IMAGE_PGBOUNCER:-"${IMAGE_BASE}:main-pgbouncer$PG_VER"} -export IMAGE_POSTGRESQL=${IMAGE_POSTGRESQL:-"${IMAGE_BASE}:main-ppg$PG_VER-postgres"} +export IMAGE_POSTGRESQL=${IMAGE_POSTGRESQL:-"perconalab/percona-distribution-postgresql:$PG_VER"} export IMAGE_BACKREST=${IMAGE_BACKREST:-"${IMAGE_BASE}:main-pgbackrest$PG_VER"} export IMAGE_UPGRADE=${IMAGE_UPGRADE:-"${IMAGE_BASE}:main-upgrade"} export BUCKET=${BUCKET:-"pg-operator-testing"} diff --git a/internal/patroni/reconcile.go b/internal/patroni/reconcile.go index 4f10093428..276a6fcc17 100644 --- a/internal/patroni/reconcile.go +++ b/internal/patroni/reconcile.go @@ -147,14 +147,21 @@ func InstancePod(ctx context.Context, // K8SPG-708 instanceInitContainer adds the instance init container func instanceInitContainer(cluster *v1beta1.PostgresCluster, container *corev1.Container, instancePod *corev1.PodTemplateSpec, inInstanceSpec *v1beta1.PostgresInstanceSetSpec, initImage string) { - instancePod.Spec.InitContainers = append(instancePod.Spec.InitContainers, k8s.InitContainer( + initContainer := k8s.InitContainer( cluster, naming.ContainerDatabase, initImage, cluster.Spec.ImagePullPolicy, initialize.RestrictedSecurityContext(true), container.Resources, - inInstanceSpec)) + inInstanceSpec) + + if cluster.CompareVersion("2.8.0") >= 0 { + // The operator's init container must be the first one to run so that the other init containers can use the installed scripts. + instancePod.Spec.InitContainers = append([]corev1.Container{initContainer}, instancePod.Spec.InitContainers...) + } else { + instancePod.Spec.InitContainers = append(instancePod.Spec.InitContainers, initContainer) + } instancePod.Spec.Volumes = append(instancePod.Spec.Volumes, corev1.Volume{ Name: pNaming.CrunchyBinVolumeName, @@ -171,7 +178,6 @@ func instanceInitContainer(cluster *v1beta1.PostgresCluster, container *corev1.C // instanceProbes adds Patroni liveness and readiness probes to container. func instanceProbes(cluster *v1beta1.PostgresCluster, container *corev1.Container) { - // Patroni uses a watchdog to ensure that PostgreSQL does not accept commits // after the leader lock expires, even if Patroni becomes unresponsive. // - https://github.com/zalando/patroni/blob/v2.0.1/docs/watchdog.rst diff --git a/percona/extensions/containers.go b/percona/extensions/containers.go index 48f6056d11..eba068ae79 100644 --- a/percona/extensions/containers.go +++ b/percona/extensions/containers.go @@ -6,6 +6,7 @@ import ( corev1 "k8s.io/api/core/v1" + "github.com/percona/percona-postgresql-operator/percona/naming" pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" ) @@ -15,24 +16,36 @@ func GetExtensionKey(pgMajor int, name, version string) string { // RelocatorContainer returns a container that will relocate extensions from the base image (i.e. pg_stat_monitor, pg_audit) // to the data directory so we don't lose them when user adds a custom extension. -func RelocatorContainer(_ *pgv2.PerconaPGCluster, image string, imagePullPolicy corev1.PullPolicy, postgresVersion int) corev1.Container { +func RelocatorContainer(cr *pgv2.PerconaPGCluster, image string, imagePullPolicy corev1.PullPolicy, postgresVersion int) corev1.Container { + mounts := []corev1.VolumeMount{ + { + Name: "postgres-data", + MountPath: "/pgdata", + }, + } + + command := "/usr/local/bin/relocate-extensions.sh" + + if cr.CompareVersion("2.8.0") >= 0 { + command = "/opt/crunchy/bin/relocate-extensions.sh" + mounts = append(mounts, corev1.VolumeMount{ + Name: naming.CrunchyBinVolumeName, + MountPath: naming.CrunchyBinVolumePath, + }) + } + return corev1.Container{ Name: fmt.Sprintf("extension-relocator-%d", postgresVersion), Image: image, ImagePullPolicy: imagePullPolicy, - Command: []string{"/usr/local/bin/relocate-extensions.sh"}, + Command: []string{command}, Env: []corev1.EnvVar{ { Name: "PG_VERSION", Value: strconv.Itoa(postgresVersion), }, }, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "postgres-data", - MountPath: "/pgdata", - }, - }, + VolumeMounts: mounts, } } From 7db5bacef7ad90ae068dc2235019104a18de4e51 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 29 Sep 2025 16:58:01 +0300 Subject: [PATCH 151/300] use pmm3.4 for e2e tests (#1291) --- e2e-tests/vars.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 501072d19b..e7274d7f81 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -32,8 +32,8 @@ export BUCKET=${BUCKET:-"pg-operator-testing"} export PMM_SERVER_VERSION=${PMM_SERVER_VERSION:-"9.9.9"} export IMAGE_PMM_CLIENT=${IMAGE_PMM_CLIENT:-"perconalab/pmm-client:dev-latest"} export IMAGE_PMM_SERVER=${IMAGE_PMM_SERVER:-"perconalab/pmm-server:dev-latest"} -export IMAGE_PMM3_CLIENT=${IMAGE_PMM3_CLIENT:-"perconalab/pmm-client:3-dev-latest"} -export IMAGE_PMM3_SERVER=${IMAGE_PMM3_SERVER:-"perconalab/pmm-server:3-dev-latest"} +export IMAGE_PMM3_CLIENT=${IMAGE_PMM3_CLIENT:-"perconalab/pmm-client:3.4"} +export IMAGE_PMM3_SERVER=${IMAGE_PMM3_SERVER:-"perconalab/pmm-server:3.4"} export PGOV1_TAG=${PGOV1_TAG:-"1.4.0"} export PGOV1_VER=${PGOV1_VER:-"14"} export MINIO_VER="5.4.0" From 7e528cebcbf05d3cc83084428058fb0a607ae1d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 11:40:42 +0300 Subject: [PATCH 152/300] CLOUD-727: Bump golang.org/x/tools from 0.36.0 to 0.37.0 (#1295) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.36.0 to 0.37.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.36.0...v0.37.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.37.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 28438fa029..5ee0db7172 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.41.0 + golang.org/x/crypto v0.42.0 google.golang.org/grpc v1.75.1 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.1 @@ -67,7 +67,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.27.0 // indirect + golang.org/x/mod v0.28.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect @@ -125,14 +125,14 @@ require ( go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.43.0 // indirect + golang.org/x/net v0.44.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/term v0.34.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.36.0 + golang.org/x/tools v0.37.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect diff --git a/go.sum b/go.sum index a746e80b01..96c6527412 100644 --- a/go.sum +++ b/go.sum @@ -271,29 +271,29 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -302,18 +302,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -321,8 +321,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 96e8f9e4d3401b37454504b4221bfbbc1e4f7360 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 11:58:18 +0300 Subject: [PATCH 153/300] CLOUD-727: Bump k8s.io/apiextensions-apiserver from 0.33.4 to 0.34.1 (#1293) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.33.4 to 0.34.1. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.33.4...v0.34.1) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.34.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 5ee0db7172..65ac7619fc 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( k8s.io/api v0.34.1 k8s.io/apimachinery v0.34.1 k8s.io/client-go v0.34.1 - k8s.io/component-base v0.33.4 + k8s.io/component-base v0.34.1 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.6.0 ) @@ -139,7 +139,7 @@ require ( google.golang.org/protobuf v1.36.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.33.4 + k8s.io/apiextensions-apiserver v0.34.1 k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 diff --git a/go.sum b/go.sum index 96c6527412..1aed0e8a58 100644 --- a/go.sum +++ b/go.sum @@ -362,14 +362,14 @@ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= -k8s.io/apiextensions-apiserver v0.33.4 h1:rtq5SeXiDbXmSwxsF0MLe2Mtv3SwprA6wp+5qh/CrOU= -k8s.io/apiextensions-apiserver v0.33.4/go.mod h1:mWXcZQkQV1GQyxeIjYApuqsn/081hhXPZwZ2URuJeSs= +k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI= +k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= -k8s.io/component-base v0.33.4 h1:Jvb/aw/tl3pfgnJ0E0qPuYLT0NwdYs1VXXYQmSuxJGY= -k8s.io/component-base v0.33.4/go.mod h1:567TeSdixWW2Xb1yYUQ7qk5Docp2kNznKL87eygY8Rc= +k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= +k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= From b6987bec6a6d2bc57506e63ce761da5e50633849 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 13:21:37 +0300 Subject: [PATCH 154/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace (#1301) Bumps [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) from 1.37.0 to 1.38.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.37.0...v1.38.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace dependency-version: 1.38.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 65ac7619fc..69031649c2 100644 --- a/go.mod +++ b/go.mod @@ -25,8 +25,8 @@ require ( go.opentelemetry.io/otel v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 - go.opentelemetry.io/otel/sdk v1.37.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 + go.opentelemetry.io/otel/sdk v1.38.0 go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.42.0 diff --git a/go.sum b/go.sum index 1aed0e8a58..b55e401deb 100644 --- a/go.sum +++ b/go.sum @@ -243,14 +243,14 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE= go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= From 8a0e093debd99fe80b113ef09c7dab1d6c685c0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 13:22:15 +0300 Subject: [PATCH 155/300] CLOUD-727: Bump github.com/go-openapi/validate from 0.24.0 to 0.25.0 (#1294) Bumps [github.com/go-openapi/validate](https://github.com/go-openapi/validate) from 0.24.0 to 0.25.0. - [Commits](https://github.com/go-openapi/validate/compare/v0.24.0...v0.25.0) --- updated-dependencies: - dependency-name: github.com/go-openapi/validate dependency-version: 0.25.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 38 ++++++++++++++-------------- go.sum | 80 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/go.mod b/go.mod index 69031649c2..71feeebf71 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.25.1 require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc github.com/go-logr/logr v1.4.3 - github.com/go-openapi/errors v0.22.2 + github.com/go-openapi/errors v0.22.3 github.com/go-openapi/runtime v0.28.0 - github.com/go-openapi/strfmt v0.23.0 + github.com/go-openapi/strfmt v0.24.0 github.com/go-openapi/swag v0.25.0 - github.com/go-openapi/validate v0.24.0 + github.com/go-openapi/validate v0.25.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.7.0 @@ -47,17 +47,18 @@ require ( github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-openapi/swag/cmdutils v0.25.0 // indirect - github.com/go-openapi/swag/conv v0.25.0 // indirect - github.com/go-openapi/swag/fileutils v0.25.0 // indirect - github.com/go-openapi/swag/jsonname v0.25.0 // indirect - github.com/go-openapi/swag/jsonutils v0.25.0 // indirect - github.com/go-openapi/swag/loading v0.25.0 // indirect - github.com/go-openapi/swag/mangling v0.25.0 // indirect + github.com/go-openapi/swag/conv v0.25.1 // indirect + github.com/go-openapi/swag/fileutils v0.25.1 // indirect + github.com/go-openapi/swag/jsonname v0.25.1 // indirect + github.com/go-openapi/swag/jsonutils v0.25.1 // indirect + github.com/go-openapi/swag/loading v0.25.1 // indirect + github.com/go-openapi/swag/mangling v0.25.1 // indirect github.com/go-openapi/swag/netutils v0.25.0 // indirect - github.com/go-openapi/swag/stringutils v0.25.0 // indirect - github.com/go-openapi/swag/typeutils v0.25.0 // indirect - github.com/go-openapi/swag/yamlutils v0.25.0 // indirect + github.com/go-openapi/swag/stringutils v0.25.1 // indirect + github.com/go-openapi/swag/typeutils v0.25.1 // indirect + github.com/go-openapi/swag/yamlutils v0.25.1 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/btree v1.1.3 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect @@ -85,11 +86,11 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-openapi/analysis v0.23.0 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/loads v0.22.0 // indirect - github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/analysis v0.24.0 // indirect + github.com/go-openapi/jsonpointer v0.22.1 // indirect + github.com/go-openapi/jsonreference v0.21.2 // indirect + github.com/go-openapi/loads v0.23.1 // indirect + github.com/go-openapi/spec v0.22.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang/protobuf v1.5.4 // indirect @@ -99,7 +100,6 @@ require ( github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect @@ -119,7 +119,7 @@ require ( github.com/swaggest/assertjson v1.9.0 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect - go.mongodb.org/mongo-driver v1.14.0 // indirect + go.mongodb.org/mongo-driver v1.17.4 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect diff --git a/go.sum b/go.sum index b55e401deb..7739c4cd45 100644 --- a/go.sum +++ b/go.sum @@ -43,52 +43,54 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= -github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.2 h1:rdxhzcBUazEcGccKqbY1Y7NS8FDcMyIRr0934jrYnZg= -github.com/go-openapi/errors v0.22.2/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco= -github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs= +github.com/go-openapi/analysis v0.24.0 h1:vE/VFFkICKyYuTWYnplQ+aVr45vlG6NcZKC7BdIXhsA= +github.com/go-openapi/analysis v0.24.0/go.mod h1:GLyoJA+bvmGGaHgpfeDh8ldpGo69fAJg7eeMDMRCIrw= +github.com/go-openapi/errors v0.22.3 h1:k6Hxa5Jg1TUyZnOwV2Lh81j8ayNw5VVYLvKrp4zFKFs= +github.com/go-openapi/errors v0.22.3/go.mod h1:+WvbaBBULWCOna//9B9TbLNGSFOfF8lY9dw4hGiEiKQ= +github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk= +github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= +github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU= +github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ= +github.com/go-openapi/loads v0.23.1 h1:H8A0dX2KDHxDzc797h0+uiCZ5kwE2+VojaQVaTlXvS0= +github.com/go-openapi/loads v0.23.1/go.mod h1:hZSXkyACCWzWPQqizAv/Ye0yhi2zzHwMmoXQ6YQml44= github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= -github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= -github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= -github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= +github.com/go-openapi/spec v0.22.0 h1:xT/EsX4frL3U09QviRIZXvkh80yibxQmtoEvyqug0Tw= +github.com/go-openapi/spec v0.22.0/go.mod h1:K0FhKxkez8YNS94XzF8YKEMULbFrRw4m15i2YUht4L0= +github.com/go-openapi/strfmt v0.24.0 h1:dDsopqbI3wrrlIzeXRbqMihRNnjzGC+ez4NQaAAJLuc= +github.com/go-openapi/strfmt v0.24.0/go.mod h1:Lnn1Bk9rZjXxU9VMADbEEOo7D7CDyKGLsSKekhFr7s4= github.com/go-openapi/swag v0.25.0 h1:xyZhlgInBg6wOtyTD5b+pzwVqHSOliAvgvKW+POFUts= github.com/go-openapi/swag v0.25.0/go.mod h1:yhsa7GJvO1JBFZccLq9uh/MawsC0PQd8sNz88VBXQlU= github.com/go-openapi/swag/cmdutils v0.25.0 h1:iYZ24DEGPEk6L1jO09vw39KfpxbG7KhS+WeQexS8U5A= github.com/go-openapi/swag/cmdutils v0.25.0/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= -github.com/go-openapi/swag/conv v0.25.0 h1:5K+e44HkOgCVE0IJTbivurzHahT62DPr2DEJqR/+4pA= -github.com/go-openapi/swag/conv v0.25.0/go.mod h1:oa1ZZnb1jubNdZlD1iAhGXt6Ic4hHtuO23MwTgAXR88= -github.com/go-openapi/swag/fileutils v0.25.0 h1:t7aQRuRfsP29dY4vfrNvDZv7RurwRHuyjUedtYVDmYY= -github.com/go-openapi/swag/fileutils v0.25.0/go.mod h1:+NXtt5xNZZqmpIpjqcujqojGFek9/w55b3ecmOdtg8M= -github.com/go-openapi/swag/jsonname v0.25.0 h1:+fuNs9gdkb2w10hgsgOBx9jtx0pvtUaDRYxD91BEpEQ= -github.com/go-openapi/swag/jsonname v0.25.0/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= -github.com/go-openapi/swag/jsonutils v0.25.0 h1:ELKpJT29T4N/AvmDqMeDFLx2QRZQOYFthzctbIX30+A= -github.com/go-openapi/swag/jsonutils v0.25.0/go.mod h1:KYL8GyGoi6tek9ajpvn0le4BWmKoUVVv8yPxklViIMo= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.0 h1:ca9vKxLnJegL2bzqXRWNabKdqVGxBzrnO8/UZnr5W0Y= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.0/go.mod h1:kjmweouyPwRUEYMSrbAidoLMGeJ5p6zdHi9BgZiqmsg= -github.com/go-openapi/swag/loading v0.25.0 h1:e9mjE5fJeaK0LTepHMtG0Ief+9ETXLFhWCx7ZfiI6LI= -github.com/go-openapi/swag/loading v0.25.0/go.mod h1:2ZCWXwVY1XYuoue8Bdjbn5GJK4/ufXbCfcvoSPFQJqM= -github.com/go-openapi/swag/mangling v0.25.0 h1:VdTfDWX5lS3yURxYHF5SK7kYelSK69Lv2xEAeudTzM8= -github.com/go-openapi/swag/mangling v0.25.0/go.mod h1:CdiMQ6pnfAgyQGSOIYnZkXvqhnnwOn997uXZMAd/7mQ= +github.com/go-openapi/swag/conv v0.25.1 h1:+9o8YUg6QuqqBM5X6rYL/p1dpWeZRhoIt9x7CCP+he0= +github.com/go-openapi/swag/conv v0.25.1/go.mod h1:Z1mFEGPfyIKPu0806khI3zF+/EUXde+fdeksUl2NiDs= +github.com/go-openapi/swag/fileutils v0.25.1 h1:rSRXapjQequt7kqalKXdcpIegIShhTPXx7yw0kek2uU= +github.com/go-openapi/swag/fileutils v0.25.1/go.mod h1:+NXtt5xNZZqmpIpjqcujqojGFek9/w55b3ecmOdtg8M= +github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU= +github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= +github.com/go-openapi/swag/jsonutils v0.25.1 h1:AihLHaD0brrkJoMqEZOBNzTLnk81Kg9cWr+SPtxtgl8= +github.com/go-openapi/swag/jsonutils v0.25.1/go.mod h1:JpEkAjxQXpiaHmRO04N1zE4qbUEg3b7Udll7AMGTNOo= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1 h1:DSQGcdB6G0N9c/KhtpYc71PzzGEIc/fZ1no35x4/XBY= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1/go.mod h1:kjmweouyPwRUEYMSrbAidoLMGeJ5p6zdHi9BgZiqmsg= +github.com/go-openapi/swag/loading v0.25.1 h1:6OruqzjWoJyanZOim58iG2vj934TysYVptyaoXS24kw= +github.com/go-openapi/swag/loading v0.25.1/go.mod h1:xoIe2EG32NOYYbqxvXgPzne989bWvSNoWoyQVWEZicc= +github.com/go-openapi/swag/mangling v0.25.1 h1:XzILnLzhZPZNtmxKaz/2xIGPQsBsvmCjrJOWGNz/ync= +github.com/go-openapi/swag/mangling v0.25.1/go.mod h1:CdiMQ6pnfAgyQGSOIYnZkXvqhnnwOn997uXZMAd/7mQ= github.com/go-openapi/swag/netutils v0.25.0 h1:/e1LPmXfF9fcOYbbaP3+SQgon1fRwe5EZ0FjpR4vAjs= github.com/go-openapi/swag/netutils v0.25.0/go.mod h1:CAkkvqnUJX8NV96tNhEQvKz8SQo2KF0f7LleiJwIeRE= -github.com/go-openapi/swag/stringutils v0.25.0 h1:iYfCF45GUeI/1Yrh8rQtTFCp5K1ToqWhUdzJZwvXvv8= -github.com/go-openapi/swag/stringutils v0.25.0/go.mod h1:JLdSAq5169HaiDUbTvArA2yQxmgn4D6h4A+4HqVvAYg= -github.com/go-openapi/swag/typeutils v0.25.0 h1:iUTsxu3F3h9v6CBzVFGXKPSBQt6d8XXgYy1YAlu+HJ8= -github.com/go-openapi/swag/typeutils v0.25.0/go.mod h1:9McMC/oCdS4BKwk2shEB7x17P6HmMmA6dQRtAkSnNb8= -github.com/go-openapi/swag/yamlutils v0.25.0 h1:apgy77seWLEM9HKDcieIgW8bG9aSZgH6nQ9THlHYgHA= -github.com/go-openapi/swag/yamlutils v0.25.0/go.mod h1:0JvBRtc0mR02IqHURUeGgS9cG+Dfms4FCGXCnsgnt7c= -github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= -github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= +github.com/go-openapi/swag/stringutils v0.25.1 h1:Xasqgjvk30eUe8VKdmyzKtjkVjeiXx1Iz0zDfMNpPbw= +github.com/go-openapi/swag/stringutils v0.25.1/go.mod h1:JLdSAq5169HaiDUbTvArA2yQxmgn4D6h4A+4HqVvAYg= +github.com/go-openapi/swag/typeutils v0.25.1 h1:rD/9HsEQieewNt6/k+JBwkxuAHktFtH3I3ysiFZqukA= +github.com/go-openapi/swag/typeutils v0.25.1/go.mod h1:9McMC/oCdS4BKwk2shEB7x17P6HmMmA6dQRtAkSnNb8= +github.com/go-openapi/swag/yamlutils v0.25.1 h1:mry5ez8joJwzvMbaTGLhw8pXUnhDK91oSJLDPF1bmGk= +github.com/go-openapi/swag/yamlutils v0.25.1/go.mod h1:cm9ywbzncy3y6uPm/97ysW8+wZ09qsks+9RS8fLWKqg= +github.com/go-openapi/validate v0.25.0 h1:JD9eGX81hDTjoY3WOzh6WqxVBVl7xjsLnvDo1GL5WPU= +github.com/go-openapi/validate v0.25.0/go.mod h1:SUY7vKrN5FiwK6LyvSwKjDfLNirSfWwHNgxd2l29Mmw= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= @@ -145,8 +147,6 @@ github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -223,8 +223,8 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= -go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= +go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.nhat.io/aferomock v0.8.0 h1:jESv25NuTpA/Wga+AOKqKI1lPKdYiBYvxpIUDJWyfPM= go.nhat.io/aferomock v0.8.0/go.mod h1:thJD/9Yeo+CcIW45u6rNU8WYc1yIWdqfOSpKcGtjAXw= go.nhat.io/grpcmock v0.32.0 h1:0qAwlE7Tc8paLbQ3TbwmucsrjW7+D3M68ozJYFWp+5c= From 692301e0711f305cea91f8daabffb9cffcd57bc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 13:25:21 +0300 Subject: [PATCH 156/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp (#1299) Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) from 1.37.0 to 1.38.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.37.0...v1.38.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp dependency-version: 1.38.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 71feeebf71..b97d5a84f0 100644 --- a/go.mod +++ b/go.mod @@ -23,8 +23,8 @@ require ( go.nhat.io/grpcmock v0.32.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 go.opentelemetry.io/otel v1.38.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 go.opentelemetry.io/otel/sdk v1.38.0 go.opentelemetry.io/otel/trace v1.38.0 @@ -42,7 +42,7 @@ require ( require ( github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/cenkalti/backoff/v5 v5.0.2 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect @@ -123,7 +123,7 @@ require ( go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect - go.opentelemetry.io/proto/otlp v1.7.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.44.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect @@ -134,9 +134,9 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.37.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/protobuf v1.36.7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect + google.golang.org/protobuf v1.36.8 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.34.1 diff --git a/go.sum b/go.sum index 7739c4cd45..87685b3682 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/bool64/dev v0.2.29 h1:x+syGyh+0eWtOzQ1ItvLzOGIWyNWnyjXpHIcpF2HvL4= github.com/bool64/dev v0.2.29/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= -github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= -github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -239,10 +239,10 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/X go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE= go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= @@ -253,8 +253,8 @@ go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6 go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= -go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= -go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= +go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -331,16 +331,16 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= -google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY= +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= -google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 8aa781a4e65f8e0e6e4d9faf821f2c1781bda76e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 13:30:32 +0300 Subject: [PATCH 157/300] CLOUD-727: Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#1298) Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.62.0 to 0.63.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.62.0...zpages/v0.63.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp dependency-version: 0.63.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b97d5a84f0..35bddd1e27 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.32.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 go.opentelemetry.io/otel v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 diff --git a/go.sum b/go.sum index 87685b3682..a6ce7473c1 100644 --- a/go.sum +++ b/go.sum @@ -235,8 +235,8 @@ go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= go.nhat.io/wait v0.1.0/go.mod h1:+ijMghc9/9zXi+HDcs49HNReprvXOZha2Q3jTOtqJrE= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= From 1098ce4e50b326203edd4c7379bd887594a0e7aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:18:04 +0300 Subject: [PATCH 158/300] CLOUD-727: Bump github.com/go-openapi/runtime from 0.28.0 to 0.29.0 (#1297) Bumps [github.com/go-openapi/runtime](https://github.com/go-openapi/runtime) from 0.28.0 to 0.29.0. - [Release notes](https://github.com/go-openapi/runtime/releases) - [Commits](https://github.com/go-openapi/runtime/compare/v0.28.0...v0.29.0) --- updated-dependencies: - dependency-name: github.com/go-openapi/runtime dependency-version: 0.29.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 5 ++--- go.sum | 14 ++++++-------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 35bddd1e27..2979276e62 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc github.com/go-logr/logr v1.4.3 github.com/go-openapi/errors v0.22.3 - github.com/go-openapi/runtime v0.28.0 + github.com/go-openapi/runtime v0.29.0 github.com/go-openapi/strfmt v0.24.0 github.com/go-openapi/swag v0.25.0 github.com/go-openapi/validate v0.25.0 @@ -64,7 +64,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/x448/float16 v0.8.4 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect @@ -105,7 +105,6 @@ require ( github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect diff --git a/go.sum b/go.sum index a6ce7473c1..99830f2dfd 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5 github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ= github.com/go-openapi/loads v0.23.1 h1:H8A0dX2KDHxDzc797h0+uiCZ5kwE2+VojaQVaTlXvS0= github.com/go-openapi/loads v0.23.1/go.mod h1:hZSXkyACCWzWPQqizAv/Ye0yhi2zzHwMmoXQ6YQml44= -github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ= -github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= +github.com/go-openapi/runtime v0.29.0 h1:Y7iDTFarS9XaFQ+fA+lBLngMwH6nYfqig1G+pHxMRO0= +github.com/go-openapi/runtime v0.29.0/go.mod h1:52HOkEmLL/fE4Pg3Kf9nxc9fYQn0UsIWyGjGIJE9dkg= github.com/go-openapi/spec v0.22.0 h1:xT/EsX4frL3U09QviRIZXvkh80yibxQmtoEvyqug0Tw= github.com/go-openapi/spec v0.22.0/go.mod h1:K0FhKxkez8YNS94XzF8YKEMULbFrRw4m15i2YUht4L0= github.com/go-openapi/strfmt v0.24.0 h1:dDsopqbI3wrrlIzeXRbqMihRNnjzGC+ez4NQaAAJLuc= @@ -169,8 +169,6 @@ github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -190,8 +188,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -233,8 +231,8 @@ go.nhat.io/matcher/v2 v2.0.0 h1:W+rbHi0hKuZHtOQH4U5g+KwyKyfVioIxrxjoGRcUETE= go.nhat.io/matcher/v2 v2.0.0/go.mod h1:cL5oYp0M9A4L8jEGqjmUfy+k7AXVDddoVt6aYIL1r5g= go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= go.nhat.io/wait v0.1.0/go.mod h1:+ijMghc9/9zXi+HDcs49HNReprvXOZha2Q3jTOtqJrE= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= From 7f6a255a13de6fa4cae1cda360c719e808eb619b Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Tue, 30 Sep 2025 18:04:24 +0300 Subject: [PATCH 159/300] K8SPG-611 fix upgrade-consistency test (#1302) --- .../tests/upgrade-consistency/01-create-cluster.yaml | 8 +++++--- e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml | 8 +++++--- e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml | 7 +++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml index 086564ae21..53c32fbcbe 100644 --- a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml @@ -8,8 +8,10 @@ commands: source ../../functions + cr_version="2.6.0" get_cr \ - | yq eval '.spec.crVersion="2.6.0"' - \ - | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ - | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:main-ppg$PG_VER-pgbackrest\"" - \ + | yq eval ".spec.crVersion=\"$cr_version\"" - \ + | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ + | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-pgbackrest\"" - \ + | yq eval ".spec.proxy.pgBouncer.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-pgbouncer\"" - \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index 1caf07a01d..f35c4dd88d 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -8,10 +8,12 @@ commands: source ../../functions + cr_version="2.7.0" get_cr \ - | yq eval ' - .spec.crVersion="2.7.0"' - \ - | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ + | yq eval ".spec.crVersion=\"$cr_version\"" - \ - \ + | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ + | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:pg-operator-$cr_version-pgbackrest$PG_VER\"" - \ + | yq eval ".spec.proxy.pgBouncer.image=\"${IMAGE_BASE}:pg-operator-$cr_version-pgbouncer$PG_VER\"" - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 8ce02b3f72..959d3aab14 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -8,9 +8,12 @@ commands: source ../../functions + cr_version="2.8.0" get_cr \ - | yq eval ' - .spec.crVersion="2.8.0"' - \ + | yq eval ".spec.crVersion=\"$cr_version\"" - \ + | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ + | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:main-pgbackrest$PG_VER\"" - \ + | yq eval ".spec.proxy.pgBouncer.image=\"${IMAGE_BASE}:main-pgbouncer$PG_VER\"" - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 From 9da4e541ed4feaf265be9ffaa10c608c2fd2596c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 11:30:06 +0300 Subject: [PATCH 160/300] CLOUD-727: Bump aquasecurity/trivy-action from 0.33.0 to 0.33.1 (#1304) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.33.0 to 0.33.1. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.33.0...0.33.1) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-version: 0.33.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/scan.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 2bbb9ad862..2302b172eb 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -31,7 +31,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/arm64) - uses: aquasecurity/trivy-action@0.33.0 + uses: aquasecurity/trivy-action@0.33.1 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64' format: 'table' @@ -50,7 +50,7 @@ jobs: make build-docker-image - name: Run Trivy vulnerability scanner image (linux/amd64) - uses: aquasecurity/trivy-action@0.33.0 + uses: aquasecurity/trivy-action@0.33.1 with: image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64' format: 'table' From a6794577936643bbcbce62a700a2793787a63858 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 11:30:28 +0300 Subject: [PATCH 161/300] CLOUD-727: Bump actions/setup-go from 5 to 6 (#1305) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- .github/workflows/reviewdog.yml | 6 +++--- .github/workflows/test.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 14622c62d7..971eb5a4a1 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -5,7 +5,7 @@ jobs: name: runner / suggester / golangci-lint runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: '^1.25.1' - uses: actions/checkout@v5 @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: '^1.25.1' - run: go install -v github.com/incu6us/goimports-reviser/v3@latest @@ -45,7 +45,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: '^1.25.1' - run: go install mvdan.cc/sh/v3/cmd/shfmt@latest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 42a332a320..deeafa53f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: - name: Clone the code uses: actions/checkout@v5 - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: '^1.25.1' - uses: actions/checkout@v5 From a1852ac4cffe6683866c1cc0808deb4f820bda71 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Fri, 3 Oct 2025 12:31:41 +0300 Subject: [PATCH 162/300] K8SPG-833: watch `envFrom` secrets (#1306) --- cmd/postgres-operator/main.go | 9 ++++ percona/controller/pgcluster/controller.go | 34 ++++++++++++-- percona/controller/pgcluster/secret.go | 7 --- .../v2/perconapgcluster_types.go | 47 +++++++++++++++++++ 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index c48f0214ac..45ff637b63 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -163,6 +163,15 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { return errors.New("missing controller in manager") } + if err := mgr.GetFieldIndexer().IndexField( + context.Background(), + &v2.PerconaPGCluster{}, + v2.IndexFieldEnvFromSecrets, + v2.EnvFromSecretsIndexerFunc, + ); err != nil { + return err + } + externalEvents := make(chan event.GenericEvent) stopChan := make(chan event.DeleteEvent) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 48e65eae35..4ef3d379cc 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -106,6 +106,7 @@ func (r *PGClusterReconciler) SetupWithManager(mgr manager.Manager) error { For(&v2.PerconaPGCluster{}). Owns(&v1beta1.PostgresCluster{}). WatchesRawSource(source.Kind(mgr.GetCache(), &corev1.Service{}, r.watchServices())). + Watches(&corev1.Secret{}, r.watchEnvFromSecrets()). WatchesRawSource(source.Kind(mgr.GetCache(), &corev1.Secret{}, r.watchSecrets())). WatchesRawSource(source.Kind(mgr.GetCache(), &batchv1.Job{}, r.watchBackupJobs())). WatchesRawSource(source.Kind(mgr.GetCache(), &v2.PerconaPGBackup{}, r.watchPGBackups())). @@ -165,6 +166,33 @@ func (r *PGClusterReconciler) watchPGBackups() handler.TypedFuncs[*v2.PerconaPGB } } +func (r *PGClusterReconciler) watchEnvFromSecrets() handler.TypedEventHandler[client.Object, reconcile.Request] { + return handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request { + log := logf.FromContext(ctx).WithName("watchEnvFromSecrets") + + secret, ok := obj.(*corev1.Secret) + if !ok { + return nil + } + + var clusters v2.PerconaPGClusterList + if err := r.Client.List(ctx, &clusters, client.MatchingFields{ + v2.IndexFieldEnvFromSecrets: secret.Name, + }, client.InNamespace(secret.Namespace)); err != nil { + log.Error(err, "Failed to list clusters by env from secrets index failed", "key", client.ObjectKeyFromObject(secret).String()) + return nil + } + + reqs := make([]reconcile.Request, 0, len(clusters.Items)) + for _, cr := range clusters.Items { + reqs = append(reqs, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(&cr), + }) + } + return reqs + }) +} + func (r *PGClusterReconciler) watchSecrets() handler.TypedFuncs[*corev1.Secret, reconcile.Request] { return handler.TypedFuncs[*corev1.Secret, reconcile.Request]{ UpdateFunc: func(ctx context.Context, e event.TypedUpdateEvent[*corev1.Secret], q workqueue.TypedRateLimitingInterface[reconcile.Request]) { @@ -281,7 +309,7 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "failed to handle monitor user password change") } - if err := r.handleEnvFromSecrets(ctx, cr); err != nil { + if err := r.reconcileEnvFromSecrets(ctx, cr); err != nil { return reconcile.Result{}, errors.Wrap(err, "failed to handle envFrom secrets") } @@ -721,7 +749,7 @@ func (r *PGClusterReconciler) reconcilePMM(ctx context.Context, cr *v2.PerconaPG return nil } -func (r *PGClusterReconciler) handleEnvFromSecrets(ctx context.Context, cr *v2.PerconaPGCluster) error { +func (r *PGClusterReconciler) reconcileEnvFromSecrets(ctx context.Context, cr *v2.PerconaPGCluster) error { m := make(map[*[]corev1.EnvFromSource]*v1beta1.Metadata) for i := 0; i < len(cr.Spec.InstanceSets); i++ { @@ -759,7 +787,7 @@ func (r *PGClusterReconciler) handleEnvFromSecrets(ctx context.Context, cr *v2.P metadata.Annotations = make(map[string]string) } - // If the currentHash is the same is the on the STS, restart will not happen + // If the currentHash is the same on the STS, restart will not happen metadata.Annotations[pNaming.AnnotationEnvVarsSecretHash] = getSecretHash(secrets...) } diff --git a/percona/controller/pgcluster/secret.go b/percona/controller/pgcluster/secret.go index 84c2cf9ec8..302894ff34 100644 --- a/percona/controller/pgcluster/secret.go +++ b/percona/controller/pgcluster/secret.go @@ -6,16 +6,13 @@ import ( "fmt" corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/logging" v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" ) func getEnvFromSecrets(ctx context.Context, cl client.Client, cr *v2.PerconaPGCluster, envFromSource []corev1.EnvFromSource) ([]corev1.Secret, error) { - log := logging.FromContext(ctx) var secrets []corev1.Secret for _, source := range envFromSource { var secret corev1.Secret @@ -23,10 +20,6 @@ func getEnvFromSecrets(ctx context.Context, cl client.Client, cr *v2.PerconaPGCl Name: source.SecretRef.Name, Namespace: cr.Namespace, }, &secret); err != nil { - if k8serrors.IsNotFound(err) { - log.V(1).Info(fmt.Sprintf("Secret %s not found", secret.Name)) - continue - } return nil, err } secrets = append(secrets, secret) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 412c83d61e..2445ce2031 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -8,6 +8,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "github.com/percona/percona-postgresql-operator/internal/config" @@ -1080,3 +1081,49 @@ const ( func (pgc PerconaPGCluster) UserMonitoring() string { return pgc.Name + "-" + naming.RolePostgresUser + "-" + UserMonitoring } + +func (cr *PerconaPGCluster) EnvFromSecrets() []string { + secrets := []string{} + + for i := 0; i < len(cr.Spec.InstanceSets); i++ { + set := &cr.Spec.InstanceSets[i] + if len(set.EnvFrom) == 0 { + continue + } + for _, envFrom := range set.EnvFrom { + if envFrom.SecretRef == nil { + continue + } + secrets = append(secrets, envFrom.SecretRef.Name) + } + } + + if len(cr.Spec.Proxy.PGBouncer.EnvFrom) > 0 { + for _, envFrom := range cr.Spec.Proxy.PGBouncer.EnvFrom { + if envFrom.SecretRef == nil { + continue + } + secrets = append(secrets, envFrom.SecretRef.Name) + } + } + + if len(cr.Spec.Backups.PGBackRest.EnvFrom) > 0 { + for _, envFrom := range cr.Spec.Backups.PGBackRest.EnvFrom { + if envFrom.SecretRef == nil { + continue + } + secrets = append(secrets, envFrom.SecretRef.Name) + } + } + return secrets +} + +const IndexFieldEnvFromSecrets = "pgCluster.envFromSecrets" //nolint:gosec + +var EnvFromSecretsIndexerFunc client.IndexerFunc = func(obj client.Object) []string { + cr, ok := obj.(*PerconaPGCluster) + if !ok { + return nil + } + return cr.EnvFromSecrets() +} From be4001faba93e644af9a5c3e6ab53f13199f515e Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 3 Oct 2025 15:57:01 +0300 Subject: [PATCH 163/300] K8SPG-781 add TestGetLatestCommitTimestamp (#1309) --- percona/watcher/wal.go | 1 + percona/watcher/wal_test.go | 47 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index d6c3da51ed..9946e85751 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -162,6 +162,7 @@ func getLatestBackup(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGC return latest, nil } +// GetLatestCommitTimestamp gets the timestamp of the latest commit. func GetLatestCommitTimestamp(ctx context.Context, cli client.Client, execCli *clientcmd.Client, cr *pgv2.PerconaPGCluster, backup *pgv2.PerconaPGBackup) (*metav1.Time, error) { log := logging.FromContext(ctx) diff --git a/percona/watcher/wal_test.go b/percona/watcher/wal_test.go index 086b29bcaf..a3dd176652 100644 --- a/percona/watcher/wal_test.go +++ b/percona/watcher/wal_test.go @@ -2,6 +2,7 @@ package watcher import ( "context" + "errors" "testing" "time" @@ -310,3 +311,49 @@ func TestGetLatestBackup(t *testing.T) { }) } } + +func TestGetLatestCommitTimestamp(t *testing.T) { + ctx := context.Background() + + tests := map[string]struct { + pods []client.Object + backup *pgv2.PerconaPGBackup + cluster *pgv2.PerconaPGCluster + expectedErr error + }{ + "primary pod not found due to invalid patroni version": { + pods: []client.Object{}, + backup: &pgv2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "backup1", + Namespace: "test-ns", + }, + Spec: pgv2.PerconaPGBackupSpec{ + PGCluster: "test-cluster", + RepoName: "repo1", + }, + }, + cluster: &pgv2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-ns", + }, + Status: pgv2.PerconaPGClusterStatus{ + Patroni: pgv2.Patroni{ + Version: "error", + }, + }, + }, + expectedErr: errors.New("failed to get patroni version: Malformed version: error: primary pod not found"), + }, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + c := testutils.BuildFakeClient(tt.pods...) + + _, err := GetLatestCommitTimestamp(ctx, c, nil, tt.cluster, tt.backup) + + assert.EqualError(t, err, tt.expectedErr.Error()) + }) + } +} From a3397663d86e423870f624fbbb2997d27d19fec7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:40:40 +0300 Subject: [PATCH 164/300] CLOUD-727: Bump github.com/onsi/ginkgo/v2 from 2.25.1 to 2.26.0 (#1313) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.25.1 to 2.26.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.25.1...v2.26.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-version: 2.26.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 26 ++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2979276e62..72b8a068c3 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.7.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 - github.com/onsi/ginkgo/v2 v2.25.1 + github.com/onsi/ginkgo/v2 v2.26.0 github.com/onsi/gomega v1.38.2 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 99830f2dfd..a395efe9b7 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,12 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= +github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= +github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= +github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= +github.com/gkampitakis/go-snaps v0.5.14 h1:3fAqdB6BCPKHDMHAKRwtPUwYexKtGrNuw8HX/T/4neo= +github.com/gkampitakis/go-snaps v0.5.14/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -91,6 +97,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= @@ -126,6 +134,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= +github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -143,10 +153,14 @@ github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 h1:Q3jQ1NkFqv5o+ github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= +github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -165,8 +179,8 @@ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= -github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY= -github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk= +github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= +github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= @@ -208,6 +222,14 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= From 18cdc80344e3d1973d1642fbe0cc234fdf368c45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:43:16 +0300 Subject: [PATCH 165/300] CLOUD-727: Bump github.com/go-openapi/swag from 0.25.0 to 0.25.1 (#1311) Bumps [github.com/go-openapi/swag](https://github.com/go-openapi/swag) from 0.25.0 to 0.25.1. - [Commits](https://github.com/go-openapi/swag/compare/v0.25.0...v0.25.1) --- updated-dependencies: - dependency-name: github.com/go-openapi/swag dependency-version: 0.25.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 72b8a068c3..bac2a8c4f0 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/go-openapi/errors v0.22.3 github.com/go-openapi/runtime v0.29.0 github.com/go-openapi/strfmt v0.24.0 - github.com/go-openapi/swag v0.25.0 + github.com/go-openapi/swag v0.25.1 github.com/go-openapi/validate v0.25.0 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 @@ -46,14 +46,14 @@ require ( github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/go-openapi/swag/cmdutils v0.25.0 // indirect + github.com/go-openapi/swag/cmdutils v0.25.1 // indirect github.com/go-openapi/swag/conv v0.25.1 // indirect github.com/go-openapi/swag/fileutils v0.25.1 // indirect github.com/go-openapi/swag/jsonname v0.25.1 // indirect github.com/go-openapi/swag/jsonutils v0.25.1 // indirect github.com/go-openapi/swag/loading v0.25.1 // indirect github.com/go-openapi/swag/mangling v0.25.1 // indirect - github.com/go-openapi/swag/netutils v0.25.0 // indirect + github.com/go-openapi/swag/netutils v0.25.1 // indirect github.com/go-openapi/swag/stringutils v0.25.1 // indirect github.com/go-openapi/swag/typeutils v0.25.1 // indirect github.com/go-openapi/swag/yamlutils v0.25.1 // indirect diff --git a/go.sum b/go.sum index a395efe9b7..06e224d932 100644 --- a/go.sum +++ b/go.sum @@ -65,10 +65,10 @@ github.com/go-openapi/spec v0.22.0 h1:xT/EsX4frL3U09QviRIZXvkh80yibxQmtoEvyqug0T github.com/go-openapi/spec v0.22.0/go.mod h1:K0FhKxkez8YNS94XzF8YKEMULbFrRw4m15i2YUht4L0= github.com/go-openapi/strfmt v0.24.0 h1:dDsopqbI3wrrlIzeXRbqMihRNnjzGC+ez4NQaAAJLuc= github.com/go-openapi/strfmt v0.24.0/go.mod h1:Lnn1Bk9rZjXxU9VMADbEEOo7D7CDyKGLsSKekhFr7s4= -github.com/go-openapi/swag v0.25.0 h1:xyZhlgInBg6wOtyTD5b+pzwVqHSOliAvgvKW+POFUts= -github.com/go-openapi/swag v0.25.0/go.mod h1:yhsa7GJvO1JBFZccLq9uh/MawsC0PQd8sNz88VBXQlU= -github.com/go-openapi/swag/cmdutils v0.25.0 h1:iYZ24DEGPEk6L1jO09vw39KfpxbG7KhS+WeQexS8U5A= -github.com/go-openapi/swag/cmdutils v0.25.0/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag v0.25.1 h1:6uwVsx+/OuvFVPqfQmOOPsqTcm5/GkBhNwLqIR916n8= +github.com/go-openapi/swag v0.25.1/go.mod h1:bzONdGlT0fkStgGPd3bhZf1MnuPkf2YAys6h+jZipOo= +github.com/go-openapi/swag/cmdutils v0.25.1 h1:nDke3nAFDArAa631aitksFGj2omusks88GF1VwdYqPY= +github.com/go-openapi/swag/cmdutils v0.25.1/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= github.com/go-openapi/swag/conv v0.25.1 h1:+9o8YUg6QuqqBM5X6rYL/p1dpWeZRhoIt9x7CCP+he0= github.com/go-openapi/swag/conv v0.25.1/go.mod h1:Z1mFEGPfyIKPu0806khI3zF+/EUXde+fdeksUl2NiDs= github.com/go-openapi/swag/fileutils v0.25.1 h1:rSRXapjQequt7kqalKXdcpIegIShhTPXx7yw0kek2uU= @@ -83,8 +83,8 @@ github.com/go-openapi/swag/loading v0.25.1 h1:6OruqzjWoJyanZOim58iG2vj934TysYVpt github.com/go-openapi/swag/loading v0.25.1/go.mod h1:xoIe2EG32NOYYbqxvXgPzne989bWvSNoWoyQVWEZicc= github.com/go-openapi/swag/mangling v0.25.1 h1:XzILnLzhZPZNtmxKaz/2xIGPQsBsvmCjrJOWGNz/ync= github.com/go-openapi/swag/mangling v0.25.1/go.mod h1:CdiMQ6pnfAgyQGSOIYnZkXvqhnnwOn997uXZMAd/7mQ= -github.com/go-openapi/swag/netutils v0.25.0 h1:/e1LPmXfF9fcOYbbaP3+SQgon1fRwe5EZ0FjpR4vAjs= -github.com/go-openapi/swag/netutils v0.25.0/go.mod h1:CAkkvqnUJX8NV96tNhEQvKz8SQo2KF0f7LleiJwIeRE= +github.com/go-openapi/swag/netutils v0.25.1 h1:2wFLYahe40tDUHfKT1GRC4rfa5T1B4GWZ+msEFA4Fl4= +github.com/go-openapi/swag/netutils v0.25.1/go.mod h1:CAkkvqnUJX8NV96tNhEQvKz8SQo2KF0f7LleiJwIeRE= github.com/go-openapi/swag/stringutils v0.25.1 h1:Xasqgjvk30eUe8VKdmyzKtjkVjeiXx1Iz0zDfMNpPbw= github.com/go-openapi/swag/stringutils v0.25.1/go.mod h1:JLdSAq5169HaiDUbTvArA2yQxmgn4D6h4A+4HqVvAYg= github.com/go-openapi/swag/typeutils v0.25.1 h1:rD/9HsEQieewNt6/k+JBwkxuAHktFtH3I3ysiFZqukA= From 2ee08203bac44fbfc4d55bf17c8763d69e0ed3e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:46:35 +0300 Subject: [PATCH 166/300] CLOUD-727: Bump github.com/grpc-ecosystem/grpc-gateway/v2 (#1312) Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.27.2 to 2.27.3. - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Changelog](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/.goreleaser.yml) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.27.2...v2.27.3) --- updated-dependencies: - dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2 dependency-version: 2.27.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index bac2a8c4f0..5c95b5ec34 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -133,9 +133,9 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.37.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect - google.golang.org/protobuf v1.36.8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.34.1 diff --git a/go.sum b/go.sum index 06e224d932..f67aa5908e 100644 --- a/go.sum +++ b/go.sum @@ -124,8 +124,8 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= @@ -351,16 +351,16 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY= -google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= +google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU= +google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= -google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 71d50b6640e80504c5bdffe47b8605b9477910d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 17:40:20 +0300 Subject: [PATCH 167/300] CLOUD-727: Bump google.golang.org/grpc from 1.75.1 to 1.76.0 (#1310) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5c95b5ec34..8f229bf4a4 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.42.0 - google.golang.org/grpc v1.75.1 + google.golang.org/grpc v1.76.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.1 k8s.io/apimachinery v0.34.1 diff --git a/go.sum b/go.sum index f67aa5908e..d121a52b61 100644 --- a/go.sum +++ b/go.sum @@ -355,8 +355,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1: google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk= google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4= google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= From 3f7f7fc66b78aaab3c2640b496aedd6ac7587c54 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 9 Oct 2025 15:44:44 +0300 Subject: [PATCH 168/300] K8SPG-872 handle certificate errors (#1314) --- internal/controller/postgrescluster/pki.go | 12 +++++++- internal/naming/dns.go | 33 ++++++++++++++++++---- internal/naming/dns_test.go | 7 +++-- internal/pgbackrest/reconcile.go | 5 +++- internal/pgbouncer/reconcile.go | 5 +++- internal/pgbouncer/reconcile_test.go | 2 ++ internal/pki/common.go | 17 ++++++++--- 7 files changed, 65 insertions(+), 16 deletions(-) diff --git a/internal/controller/postgrescluster/pki.go b/internal/controller/postgrescluster/pki.go index 8fad9f6da6..2568712983 100644 --- a/internal/controller/postgrescluster/pki.go +++ b/internal/controller/postgrescluster/pki.go @@ -176,7 +176,17 @@ func (r *Reconciler) reconcileClusterCertificate( r.Client.Get(ctx, client.ObjectKeyFromObject(existing), existing))) leaf := &pki.LeafCertificate{} - dnsNames := append(naming.ServiceDNSNames(ctx, primaryService), naming.ServiceDNSNames(ctx, replicaService)...) + primaryServiceDNSNames, err := naming.ServiceDNSNames(ctx, primaryService) + if err != nil { + return nil, errors.Wrap(err, "get primary service dns names") + } + + replicaServiceDNSNames, err := naming.ServiceDNSNames(ctx, replicaService) + if err != nil { + return nil, errors.Wrap(err, "get replica service dns names") + } + + dnsNames := append(primaryServiceDNSNames, replicaServiceDNSNames...) dnsFQDN := dnsNames[0] if err == nil { diff --git a/internal/naming/dns.go b/internal/naming/dns.go index d3351a5d70..243c83e833 100644 --- a/internal/naming/dns.go +++ b/internal/naming/dns.go @@ -9,6 +9,7 @@ import ( "net" "strings" + "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" ) @@ -35,7 +36,17 @@ func InstancePodDNSNames(ctx context.Context, instance *appsv1.StatefulSet) []st // RepoHostPodDNSNames returns the possible DNS names for a pgBackRest repository host Pod. // The first name is the fully qualified domain name (FQDN). -func RepoHostPodDNSNames(ctx context.Context, repoHost *appsv1.StatefulSet) []string { +func RepoHostPodDNSNames(ctx context.Context, repoHost *appsv1.StatefulSet) ([]string, error) { + if repoHost.Namespace == "" { + return nil, errors.New("repoHost.Namespace is empty") + } + if repoHost.Name == "" { + return nil, errors.New("repoHost.Name is empty") + } + if repoHost.Spec.ServiceName == "" { + return nil, errors.New("repoHost.Spec.ServiceName is empty") + } + var ( domain = KubernetesClusterDomain(ctx) namespace = repoHost.Namespace @@ -50,12 +61,20 @@ func RepoHostPodDNSNames(ctx context.Context, repoHost *appsv1.StatefulSet) []st name + "." + namespace + ".svc", name + "." + namespace, name, - } + }, nil } // ServiceDNSNames returns the possible DNS names for service. The first name // is the fully qualified domain name (FQDN). -func ServiceDNSNames(ctx context.Context, service *corev1.Service) []string { +func ServiceDNSNames(ctx context.Context, service *corev1.Service) ([]string, error) { + if service.Name == "" { + return nil, errors.New("service.Name is empty") + } + + if service.Namespace == "" { + return nil, errors.New("service.Namespace is empty") + } + domain := KubernetesClusterDomain(ctx) return []string{ @@ -63,7 +82,7 @@ func ServiceDNSNames(ctx context.Context, service *corev1.Service) []string { service.Name + "." + service.Namespace + ".svc", service.Name + "." + service.Namespace, service.Name, - } + }, nil } // KubernetesClusterDomain looks up the Kubernetes cluster domain name. @@ -78,11 +97,13 @@ func KubernetesClusterDomain(ctx context.Context) string { cname, err := net.DefaultResolver.LookupCNAME(ctx, api) if err == nil { - return strings.TrimPrefix(cname, api+".") + // The cname returned from the LookupCNAME can be `kubernetes.default.svc.cluster.local.` + // Since go stdlib validates and rejects DNS with the dot suffix, the operator has to trim it. + return strings.TrimSuffix(strings.TrimPrefix(cname, api+"."), ".") } span.RecordError(err) // The kubeadm default is "cluster.local" and is adequate when not running // in an actual Kubernetes cluster. - return "cluster.local." + return "cluster.local" } diff --git a/internal/naming/dns_test.go b/internal/naming/dns_test.go index e7e2ea9dc6..d9025e317f 100644 --- a/internal/naming/dns_test.go +++ b/internal/naming/dns_test.go @@ -35,7 +35,7 @@ func TestInstancePodDNSNames(t *testing.T) { assert.Assert(t, len(names[0]) > len(names[1]), "expected FQDN first, got %q", names[0]) assert.Assert(t, strings.HasPrefix(names[0], names[1]+"."), "wrong FQDN: %q", names[0]) - assert.Assert(t, strings.HasSuffix(names[0], "."), "expected root, got %q", names[0]) + assert.Assert(t, !strings.HasSuffix(names[0], "."), "not expected root, got %q", names[0]) } func TestServiceDNSNames(t *testing.T) { @@ -46,7 +46,8 @@ func TestServiceDNSNames(t *testing.T) { service.Namespace = "baltia" service.Name = "the-primary" - names := ServiceDNSNames(ctx, service) + names, err := ServiceDNSNames(ctx, service) + assert.NilError(t, err) assert.Assert(t, len(names) > 0) assert.DeepEqual(t, names[1:], []string{ @@ -57,5 +58,5 @@ func TestServiceDNSNames(t *testing.T) { assert.Assert(t, len(names[0]) > len(names[1]), "expected FQDN first, got %q", names[0]) assert.Assert(t, strings.HasPrefix(names[0], names[1]+"."), "wrong FQDN: %q", names[0]) - assert.Assert(t, strings.HasSuffix(names[0], "."), "expected root, got %q", names[0]) + assert.Assert(t, !strings.HasSuffix(names[0], "."), "not expected root, got %q", names[0]) } diff --git a/internal/pgbackrest/reconcile.go b/internal/pgbackrest/reconcile.go index 40e2faf408..8d2b831dc2 100644 --- a/internal/pgbackrest/reconcile.go +++ b/internal/pgbackrest/reconcile.go @@ -551,7 +551,10 @@ func Secret(ctx context.Context, // The client verifies the "pg-host" or "repo-host" option it used is // present in the DNS names of the server certificate. leaf := &pki.LeafCertificate{} - dnsNames := naming.RepoHostPodDNSNames(ctx, inRepoHost) + dnsNames, err := naming.RepoHostPodDNSNames(ctx, inRepoHost) + if err != nil { + return errors.Wrap(err, "failed to resolve repo host pod DNS names") + } commonName := dnsNames[0] // FQDN if err == nil { diff --git a/internal/pgbouncer/reconcile.go b/internal/pgbouncer/reconcile.go index 9505949af5..835d6f157e 100644 --- a/internal/pgbouncer/reconcile.go +++ b/internal/pgbouncer/reconcile.go @@ -73,7 +73,10 @@ func Secret(ctx context.Context, if inCluster.Spec.Proxy.PGBouncer.CustomTLSSecret == nil { leaf := &pki.LeafCertificate{} - dnsNames := naming.ServiceDNSNames(ctx, inService) + dnsNames, err := naming.ServiceDNSNames(ctx, inService) + if err != nil { + return errors.Wrap(err, "get service dns names") + } dnsFQDN := dnsNames[0] if err == nil { diff --git a/internal/pgbouncer/reconcile_test.go b/internal/pgbouncer/reconcile_test.go index db0730d188..a8c70a9335 100644 --- a/internal/pgbouncer/reconcile_test.go +++ b/internal/pgbouncer/reconcile_test.go @@ -57,6 +57,8 @@ func TestSecret(t *testing.T) { ctx := context.Background() cluster := new(v1beta1.PostgresCluster) service := new(corev1.Service) + service.Namespace = "ns1" + service.Name = "some-name" existing := new(corev1.Secret) intent := new(corev1.Secret) diff --git a/internal/pki/common.go b/internal/pki/common.go index fbe9421f8b..a646cb8961 100644 --- a/internal/pki/common.go +++ b/internal/pki/common.go @@ -10,8 +10,11 @@ import ( "crypto/rand" "crypto/x509" "crypto/x509/pkix" + "fmt" "math/big" "time" + + "github.com/pkg/errors" ) // certificateSignatureAlgorithm is ECDSA with SHA-384, the recommended @@ -59,9 +62,12 @@ func generateLeafCertificate( bytes, err := x509.CreateCertificate(rand.Reader, template, signer, signeePublic, signerPrivate) + if err != nil { + return nil, errors.Wrap(err, "error creating certificate") + } - parsed, _ := x509.ParseCertificate(bytes) - return parsed, err + parsed, err := x509.ParseCertificate(bytes) + return parsed, errors.Wrap(err, fmt.Sprintf("error parsing certificate with dns names: %s", dnsNames)) } func generateRootCertificate( @@ -89,7 +95,10 @@ func generateRootCertificate( // A root certificate is self-signed, so pass in the template twice. bytes, err := x509.CreateCertificate(rand.Reader, template, template, privateKey.Public(), privateKey) + if err != nil { + return nil, errors.Wrap(err, "error creating certificate") + } - parsed, _ := x509.ParseCertificate(bytes) - return parsed, err + parsed, err := x509.ParseCertificate(bytes) + return parsed, errors.Wrap(err, "error parsing certificate") } From 32cc445dd1d9c8c28bb9bca45bd62ee4e16d75b0 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 9 Oct 2025 18:03:06 +0300 Subject: [PATCH 169/300] K8SPG-862 module github.com/percona/percona-postgresql-operator/v2 (#1308) --- .golangci.yaml | 2 +- Jenkinsfile | 2 +- cmd/extension-installer/main.go | 2 +- cmd/postgres-operator/main.go | 36 +++++++++---------- go.mod | 2 +- internal/bridge/client.go | 2 +- internal/bridge/client_test.go | 2 +- .../crunchybridgecluster_controller.go | 21 ++++++----- .../crunchybridgecluster_controller_test.go | 12 +++---- .../bridge/crunchybridgecluster/delete.go | 6 ++-- .../crunchybridgecluster/delete_test.go | 4 +-- .../crunchybridgecluster/helpers_test.go | 8 ++--- .../crunchybridgecluster/mock_bridge_api.go | 6 ++-- .../bridge/crunchybridgecluster/postgres.go | 6 ++-- .../crunchybridgecluster/postgres_test.go | 6 ++-- .../bridge/crunchybridgecluster/watches.go | 2 +- .../crunchybridgecluster/watches_test.go | 2 +- internal/bridge/installation.go | 6 ++-- internal/bridge/installation_test.go | 4 +-- internal/config/config.go | 2 +- internal/config/config_test.go | 2 +- internal/controller/pgupgrade/jobs.go | 8 ++--- internal/controller/pgupgrade/jobs_test.go | 8 ++--- internal/controller/pgupgrade/labels.go | 2 +- .../pgupgrade/pgupgrade_controller.go | 8 ++--- internal/controller/pgupgrade/registration.go | 4 +-- .../controller/pgupgrade/registration_test.go | 10 +++--- internal/controller/pgupgrade/utils.go | 4 +-- internal/controller/pgupgrade/world.go | 2 +- internal/controller/pgupgrade/world_test.go | 6 ++-- internal/controller/postgrescluster/apply.go | 2 +- .../controller/postgrescluster/apply_test.go | 2 +- .../controller/postgrescluster/cluster.go | 12 +++---- .../postgrescluster/cluster_test.go | 12 +++---- .../controller/postgrescluster/controller.go | 32 ++++++++--------- .../postgrescluster/controller_ref_manager.go | 8 ++--- .../controller_ref_manager_test.go | 4 +-- .../postgrescluster/controller_test.go | 8 ++--- internal/controller/postgrescluster/delete.go | 4 +-- .../postgrescluster/helpers_test.go | 10 +++--- .../controller/postgrescluster/instance.go | 24 ++++++------- .../postgrescluster/instance_rollout_test.go | 8 ++--- .../postgrescluster/instance_test.go | 16 ++++----- .../controller/postgrescluster/patroni.go | 14 ++++---- .../postgrescluster/patroni_test.go | 10 +++--- .../controller/postgrescluster/pgadmin.go | 14 ++++---- .../postgrescluster/pgadmin_test.go | 10 +++--- .../controller/postgrescluster/pgbackrest.go | 28 +++++++-------- .../postgrescluster/pgbackrest_test.go | 18 +++++----- .../controller/postgrescluster/pgbouncer.go | 14 ++++---- .../postgrescluster/pgbouncer_test.go | 10 +++--- .../controller/postgrescluster/pgmonitor.go | 20 +++++------ .../postgrescluster/pgmonitor_test.go | 12 +++---- internal/controller/postgrescluster/pki.go | 6 ++-- .../controller/postgrescluster/pki_test.go | 8 ++--- .../postgrescluster/pod_disruption_budget.go | 4 +-- .../pod_disruption_budget_test.go | 6 ++-- .../controller/postgrescluster/postgres.go | 28 +++++++-------- .../postgrescluster/postgres_test.go | 20 +++++------ internal/controller/postgrescluster/rbac.go | 8 ++--- .../controller/postgrescluster/snapshots.go | 14 ++++---- .../postgrescluster/snapshots_test.go | 16 ++++----- .../controller/postgrescluster/suite_test.go | 4 +-- .../postgrescluster/topology_test.go | 2 +- internal/controller/postgrescluster/util.go | 6 ++-- .../controller/postgrescluster/util_test.go | 6 ++-- .../controller/postgrescluster/volumes.go | 12 +++---- .../postgrescluster/volumes_test.go | 14 ++++---- .../controller/postgrescluster/watches.go | 4 +-- .../controller/runtime/conversion_test.go | 2 +- internal/controller/runtime/runtime.go | 4 +-- .../standalone_pgadmin/configmap.go | 6 ++-- .../standalone_pgadmin/configmap_test.go | 6 ++-- .../standalone_pgadmin/controller.go | 6 ++-- .../standalone_pgadmin/controller_test.go | 4 +-- .../standalone_pgadmin/helpers_test.go | 2 +- .../standalone_pgadmin/helpers_unit_test.go | 4 +-- internal/controller/standalone_pgadmin/pod.go | 8 ++--- .../controller/standalone_pgadmin/pod_test.go | 6 ++-- .../standalone_pgadmin/postgrescluster.go | 4 +-- .../controller/standalone_pgadmin/service.go | 6 ++-- .../standalone_pgadmin/service_test.go | 4 +-- .../standalone_pgadmin/statefulset.go | 6 ++-- .../standalone_pgadmin/statefulset_test.go | 10 +++--- .../controller/standalone_pgadmin/users.go | 6 ++-- .../standalone_pgadmin/users_test.go | 10 +++--- .../controller/standalone_pgadmin/volume.go | 4 +-- .../standalone_pgadmin/volume_test.go | 14 ++++---- .../controller/standalone_pgadmin/watches.go | 2 +- .../standalone_pgadmin/watches_test.go | 4 +-- internal/initialize/intstr_test.go | 2 +- internal/initialize/metadata_test.go | 2 +- internal/initialize/primitives_test.go | 2 +- internal/initialize/security_test.go | 2 +- internal/naming/names.go | 4 +-- internal/naming/names_test.go | 2 +- internal/naming/selectors.go | 2 +- internal/naming/selectors_test.go | 2 +- internal/naming/telemetry.go | 2 +- internal/patroni/api.go | 2 +- internal/patroni/certificates_test.go | 2 +- internal/patroni/config.go | 8 ++--- internal/patroni/config_test.go | 12 +++---- internal/patroni/rbac.go | 2 +- internal/patroni/rbac_test.go | 4 +-- internal/patroni/reconcile.go | 16 ++++----- internal/patroni/reconcile_test.go | 10 +++--- internal/pgadmin/config.go | 2 +- internal/pgadmin/config_test.go | 6 ++-- internal/pgadmin/reconcile.go | 8 ++--- internal/pgadmin/reconcile_test.go | 6 ++-- internal/pgadmin/users.go | 6 ++-- internal/pgadmin/users_test.go | 6 ++-- internal/pgaudit/postgres.go | 4 +-- internal/pgaudit/postgres_test.go | 2 +- internal/pgbackrest/certificates.go | 2 +- internal/pgbackrest/certificates_test.go | 2 +- internal/pgbackrest/config.go | 10 +++--- internal/pgbackrest/config_test.go | 10 +++--- internal/pgbackrest/helpers_test.go | 2 +- internal/pgbackrest/pgbackrest.go | 2 +- internal/pgbackrest/pgbackrest_test.go | 4 +-- internal/pgbackrest/postgres.go | 4 +-- internal/pgbackrest/postgres_test.go | 4 +-- internal/pgbackrest/rbac.go | 2 +- internal/pgbackrest/rbac_test.go | 4 +-- internal/pgbackrest/reconcile.go | 14 ++++---- internal/pgbackrest/reconcile_test.go | 10 +++--- internal/pgbackrest/util.go | 2 +- internal/pgbackrest/util_test.go | 2 +- internal/pgbouncer/assertions_test.go | 2 +- internal/pgbouncer/certificates_test.go | 2 +- internal/pgbouncer/config.go | 4 +-- internal/pgbouncer/config_test.go | 6 ++-- internal/pgbouncer/postgres.go | 8 ++--- internal/pgbouncer/reconcile.go | 14 ++++---- internal/pgbouncer/reconcile_test.go | 12 +++---- internal/pgmonitor/api.go | 2 +- internal/pgmonitor/exporter.go | 4 +-- internal/pgmonitor/exporter_test.go | 4 +-- internal/pgmonitor/postgres.go | 6 ++-- internal/pgmonitor/postgres_test.go | 4 +-- internal/pgmonitor/util.go | 4 +-- internal/pgmonitor/util_test.go | 2 +- internal/pgrepack/postgres.go | 4 +-- internal/pgstatmonitor/pgstatmonitor.go | 4 +-- internal/pgstatmonitor/pgstatmonitor_test.go | 2 +- internal/pgstatstatements/pgstatstatement.go | 4 +-- .../pgstatstatements/pgstatstatement_test.go | 2 +- internal/pgvector/postgres.go | 4 +-- internal/pki/encoding_test.go | 2 +- internal/pki/pki_test.go | 2 +- internal/pmm/hba.go | 4 +-- internal/postgis/postgis.go | 4 +-- internal/postgres/assertions_test.go | 2 +- internal/postgres/config.go | 8 ++--- internal/postgres/config_test.go | 6 ++-- internal/postgres/databases.go | 2 +- internal/postgres/databases_test.go | 2 +- internal/postgres/exec_test.go | 2 +- internal/postgres/hba_test.go | 2 +- internal/postgres/huge_pages.go | 2 +- internal/postgres/huge_pages_test.go | 4 +-- internal/postgres/reconcile.go | 10 +++--- internal/postgres/reconcile_test.go | 12 +++---- internal/postgres/users.go | 8 ++--- internal/postgres/users_test.go | 4 +-- internal/registration/interface.go | 2 +- internal/registration/runner.go | 4 +-- internal/registration/runner_test.go | 2 +- internal/testing/require/kubernetes.go | 2 +- .../validation/postgrescluster_test.go | 6 ++-- internal/upgradecheck/header.go | 10 +++--- internal/upgradecheck/header_test.go | 12 +++---- internal/upgradecheck/helpers_test.go | 6 ++-- internal/upgradecheck/http.go | 2 +- internal/upgradecheck/http_test.go | 6 ++-- percona/controller/pgbackup/controller.go | 18 +++++----- .../controller/pgbackup/controller_test.go | 8 ++--- percona/controller/pgbackup/testutils_test.go | 8 ++--- percona/controller/pgcluster/backup.go | 12 +++---- percona/controller/pgcluster/backup_test.go | 6 ++-- percona/controller/pgcluster/controller.go | 34 +++++++++--------- .../controller/pgcluster/controller_test.go | 12 +++---- percona/controller/pgcluster/finalizer.go | 10 +++--- .../controller/pgcluster/finalizer_test.go | 6 ++-- percona/controller/pgcluster/restore.go | 6 ++-- percona/controller/pgcluster/schedule.go | 12 +++---- percona/controller/pgcluster/secret.go | 2 +- percona/controller/pgcluster/status.go | 8 ++--- percona/controller/pgcluster/status_test.go | 8 ++--- percona/controller/pgcluster/suite_test.go | 4 +-- .../controller/pgcluster/testutils_test.go | 16 ++++----- percona/controller/pgcluster/version.go | 10 +++--- percona/controller/pgcluster/version_test.go | 4 +-- percona/controller/pgrestore/controller.go | 12 +++---- percona/controller/pgupgrade/controller.go | 11 +++--- percona/controller/utils.go | 4 +-- percona/extensions/containers.go | 4 +-- percona/k8s/testutils_test.go | 8 ++--- percona/k8s/util.go | 6 ++-- percona/k8s/util_test.go | 2 +- percona/pgbackrest/pgbackrest.go | 6 ++-- percona/pmm/pmm.go | 2 +- percona/pmm/pmm_test.go | 4 +-- percona/postgres/common.go | 2 +- percona/runtime/runtime.go | 8 ++--- percona/testutils/client.go | 4 +-- .../client/api_version_proto_client.go | 2 +- .../version_service_apply_responses.go | 2 +- .../version_service_operator_responses.go | 2 +- .../version_service_product_responses.go | 2 +- percona/version/version.go | 4 +-- percona/version/version_test.go | 4 +-- percona/watcher/wal.go | 10 +++--- percona/watcher/wal_test.go | 4 +-- .../v2/perconapgbackup_types.go | 2 +- .../v2/perconapgcluster_types.go | 12 +++---- .../v2/perconapgcluster_types_test.go | 4 +-- .../v2/perconapgupgrade_types.go | 2 +- .../v2/zz_generated.deepcopy.go | 2 +- .../v1beta1/postgrescluster_types.go | 2 +- 222 files changed, 738 insertions(+), 740 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 1d6c55067b..fb09699286 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -54,7 +54,7 @@ linters: desc: Should be used only in tests. - pkg: testing/* desc: The "testing" packages should be used only in tests. - - pkg: github.com/percona/percona-postgresql-operator/internal/testing/* + - pkg: github.com/percona/percona-postgresql-operator/v2/internal/testing/* desc: The "internal/testing" packages should be used only in tests. tests: files: diff --git a/Jenkinsfile b/Jenkinsfile index a56d6b214f..fad0380576 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -498,7 +498,7 @@ pipeline { -e GO111MODULE=on \ golang:1.25.1 sh -c ' go install github.com/google/go-licenses@latest; - /go/bin/go-licenses csv github.com/percona/percona-postgresql-operator/cmd/postgres-operator \ + /go/bin/go-licenses csv github.com/percona/percona-postgresql-operator/v2/cmd/postgres-operator \ | cut -d , -f 3 \ | sort -u \ > go-licenses-new || : diff --git a/cmd/extension-installer/main.go b/cmd/extension-installer/main.go index 4275e49b3e..6f628e0f85 100644 --- a/cmd/extension-installer/main.go +++ b/cmd/extension-installer/main.go @@ -7,7 +7,7 @@ import ( "os" "path" - "github.com/percona/percona-postgresql-operator/percona/extensions" + "github.com/percona/percona-postgresql-operator/v2/percona/extensions" ) func main() { diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 45ff637b63..6244d92223 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -27,24 +27,24 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/controller/pgupgrade" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/controller/standalone_pgadmin" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/upgradecheck" - perconaController "github.com/percona/percona-postgresql-operator/percona/controller" - "github.com/percona/percona-postgresql-operator/percona/controller/pgbackup" - "github.com/percona/percona-postgresql-operator/percona/controller/pgcluster" - "github.com/percona/percona-postgresql-operator/percona/controller/pgrestore" - perconaPGUpgrade "github.com/percona/percona-postgresql-operator/percona/controller/pgupgrade" - perconaRuntime "github.com/percona/percona-postgresql-operator/percona/runtime" - "github.com/percona/percona-postgresql-operator/percona/utils/registry" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/pgupgrade" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/standalone_pgadmin" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/upgradecheck" + perconaController "github.com/percona/percona-postgresql-operator/v2/percona/controller" + "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgbackup" + "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgcluster" + "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgrestore" + perconaPGUpgrade "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgupgrade" + perconaRuntime "github.com/percona/percona-postgresql-operator/v2/percona/runtime" + "github.com/percona/percona-postgresql-operator/v2/percona/utils/registry" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var ( diff --git a/go.mod b/go.mod index 8f229bf4a4..7be5065fca 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/percona/percona-postgresql-operator +module github.com/percona/percona-postgresql-operator/v2 go 1.25.1 diff --git a/internal/bridge/client.go b/internal/bridge/client.go index 81d066124f..8d250c4995 100644 --- a/internal/bridge/client.go +++ b/internal/bridge/client.go @@ -20,7 +20,7 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const defaultAPI = "https://api.crunchybridge.com" diff --git a/internal/bridge/client_test.go b/internal/bridge/client_test.go index 6b4455f764..c0ccf630ad 100644 --- a/internal/bridge/client_test.go +++ b/internal/bridge/client_test.go @@ -19,7 +19,7 @@ import ( "gotest.tools/v3/assert" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" ) var testApiKey = "9012" diff --git a/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller.go b/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller.go index fbbdab045f..cbd9990cf5 100644 --- a/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller.go +++ b/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller.go @@ -21,11 +21,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/event" - "github.com/percona/percona-postgresql-operator/internal/bridge" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - pgoRuntime "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/bridge" + pgoRuntime "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // CrunchyBridgeClusterReconciler reconciles a CrunchyBridgeCluster object @@ -223,7 +222,7 @@ func (r *CrunchyBridgeClusterReconciler) Reconcile(ctx context.Context, req ctrl // TODO(crunchybridgecluster): Do we want the operator to interrupt // upgrades created through the GUI/API? if len(crunchybridgecluster.Status.OngoingUpgrade) != 0 { - return runtime.RequeueWithoutBackoff(3 * time.Minute), nil + return pgoRuntime.RequeueWithoutBackoff(3 * time.Minute), nil } // Check if there's an upgrade difference for the three upgradeable fields that hit the upgrade endpoint @@ -253,7 +252,7 @@ func (r *CrunchyBridgeClusterReconciler) Reconcile(ctx context.Context, req ctrl log.Info("Reconciled") // TODO(crunchybridgecluster): do we always want to requeue? Does the Watch mean we // don't need this, or do we want both? - return runtime.RequeueWithoutBackoff(3 * time.Minute), nil + return pgoRuntime.RequeueWithoutBackoff(3 * time.Minute), nil } // reconcileBridgeConnectionSecret looks for the Bridge connection secret specified by the cluster, @@ -403,7 +402,7 @@ func (r *CrunchyBridgeClusterReconciler) handleCreateCluster(ctx context.Context Message: "The condition of the upgrade(s) is unknown.", }) - return runtime.RequeueWithoutBackoff(3 * time.Minute) + return pgoRuntime.RequeueWithoutBackoff(3 * time.Minute) } // handleGetCluster handles getting the cluster details from Bridge and @@ -564,7 +563,7 @@ func (r *CrunchyBridgeClusterReconciler) handleUpgrade(ctx context.Context, }) } - return runtime.RequeueWithoutBackoff(3 * time.Minute) + return pgoRuntime.RequeueWithoutBackoff(3 * time.Minute) } // handleUpgradeHA handles upgrades that hit the @@ -611,7 +610,7 @@ func (r *CrunchyBridgeClusterReconciler) handleUpgradeHA(ctx context.Context, }) } - return runtime.RequeueWithoutBackoff(3 * time.Minute) + return pgoRuntime.RequeueWithoutBackoff(3 * time.Minute) } // handleUpdate handles upgrades that hit the "PATCH /clusters/" endpoint @@ -656,7 +655,7 @@ func (r *CrunchyBridgeClusterReconciler) handleUpdate(ctx context.Context, clusterUpdate.ClusterName, *clusterUpdate.IsProtected), }) - return runtime.RequeueWithoutBackoff(3 * time.Minute) + return pgoRuntime.RequeueWithoutBackoff(3 * time.Minute) } // GetSecretKeys gets the secret and returns the expected API key and team id diff --git a/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller_test.go b/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller_test.go index b1a6791799..dfe08319d0 100644 --- a/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller_test.go +++ b/internal/bridge/crunchybridgecluster/crunchybridgecluster_controller_test.go @@ -19,12 +19,12 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/bridge" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/bridge" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var testTeamId = "5678" diff --git a/internal/bridge/crunchybridgecluster/delete.go b/internal/bridge/crunchybridgecluster/delete.go index 0749e38654..0dd6369efd 100644 --- a/internal/bridge/crunchybridgecluster/delete.go +++ b/internal/bridge/crunchybridgecluster/delete.go @@ -11,9 +11,9 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const finalizer = "crunchybridgecluster.postgres-operator.crunchydata.com/finalizer" diff --git a/internal/bridge/crunchybridgecluster/delete_test.go b/internal/bridge/crunchybridgecluster/delete_test.go index 543881c7bc..bbc0d6036a 100644 --- a/internal/bridge/crunchybridgecluster/delete_test.go +++ b/internal/bridge/crunchybridgecluster/delete_test.go @@ -14,8 +14,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/bridge" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/bridge" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) func TestHandleDeleteCluster(t *testing.T) { diff --git a/internal/bridge/crunchybridgecluster/helpers_test.go b/internal/bridge/crunchybridgecluster/helpers_test.go index ad14b32751..74d2b64b5f 100644 --- a/internal/bridge/crunchybridgecluster/helpers_test.go +++ b/internal/bridge/crunchybridgecluster/helpers_test.go @@ -17,10 +17,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/bridge" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/bridge" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // Scale extends d according to PGO_TEST_TIMEOUT_SCALE. diff --git a/internal/bridge/crunchybridgecluster/mock_bridge_api.go b/internal/bridge/crunchybridgecluster/mock_bridge_api.go index 081bb60a47..febd318ca6 100644 --- a/internal/bridge/crunchybridgecluster/mock_bridge_api.go +++ b/internal/bridge/crunchybridgecluster/mock_bridge_api.go @@ -11,10 +11,10 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/bridge" - "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/bridge" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type TestBridgeClient struct { diff --git a/internal/bridge/crunchybridgecluster/postgres.go b/internal/bridge/crunchybridgecluster/postgres.go index 36e88c17e5..9bb6090aba 100644 --- a/internal/bridge/crunchybridgecluster/postgres.go +++ b/internal/bridge/crunchybridgecluster/postgres.go @@ -15,9 +15,9 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/bridge" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/bridge" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // generatePostgresRoleSecret returns a Secret containing a password and diff --git a/internal/bridge/crunchybridgecluster/postgres_test.go b/internal/bridge/crunchybridgecluster/postgres_test.go index be462e997b..80add28eb2 100644 --- a/internal/bridge/crunchybridgecluster/postgres_test.go +++ b/internal/bridge/crunchybridgecluster/postgres_test.go @@ -15,9 +15,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/bridge" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/bridge" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGeneratePostgresRoleSecret(t *testing.T) { diff --git a/internal/bridge/crunchybridgecluster/watches.go b/internal/bridge/crunchybridgecluster/watches.go index 3774a0a211..a0b264346b 100644 --- a/internal/bridge/crunchybridgecluster/watches.go +++ b/internal/bridge/crunchybridgecluster/watches.go @@ -14,7 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // watchForRelatedSecret handles create/update/delete events for secrets, diff --git a/internal/bridge/crunchybridgecluster/watches_test.go b/internal/bridge/crunchybridgecluster/watches_test.go index 02f5215fdf..bc91930f75 100644 --- a/internal/bridge/crunchybridgecluster/watches_test.go +++ b/internal/bridge/crunchybridgecluster/watches_test.go @@ -12,7 +12,7 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) func TestFindCrunchyBridgeClustersForSecret(t *testing.T) { diff --git a/internal/bridge/installation.go b/internal/bridge/installation.go index 3e8fdf4e17..a7c15e1499 100644 --- a/internal/bridge/installation.go +++ b/internal/bridge/installation.go @@ -25,9 +25,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" ) // self is a singleton Installation. See [InstallationReconciler]. diff --git a/internal/bridge/installation_test.go b/internal/bridge/installation_test.go index 73511d6017..88d114f0c6 100644 --- a/internal/bridge/installation_test.go +++ b/internal/bridge/installation_test.go @@ -20,8 +20,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) func TestExtractSecretContract(t *testing.T) { diff --git a/internal/config/config.go b/internal/config/config.go index 032663fea9..5eff8c7c51 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -8,7 +8,7 @@ import ( "fmt" "os" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // defaultFromEnv reads the environment variable key when value is empty. diff --git a/internal/config/config_test.go b/internal/config/config_test.go index f233ff14d7..12c80d65ce 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -11,7 +11,7 @@ import ( "gotest.tools/v3/assert" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestFetchKeyCommand(t *testing.T) { diff --git a/internal/controller/pgupgrade/jobs.go b/internal/controller/pgupgrade/jobs.go index bab9d49637..9ce675f89b 100644 --- a/internal/controller/pgupgrade/jobs.go +++ b/internal/controller/pgupgrade/jobs.go @@ -16,10 +16,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // Upgrade job diff --git a/internal/controller/pgupgrade/jobs_test.go b/internal/controller/pgupgrade/jobs_test.go index 737f023ce7..79075b1c24 100644 --- a/internal/controller/pgupgrade/jobs_test.go +++ b/internal/controller/pgupgrade/jobs_test.go @@ -16,10 +16,10 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestLargestWholeCPU(t *testing.T) { diff --git a/internal/controller/pgupgrade/labels.go b/internal/controller/pgupgrade/labels.go index a5eda21d7a..93f9e6f7cd 100644 --- a/internal/controller/pgupgrade/labels.go +++ b/internal/controller/pgupgrade/labels.go @@ -5,7 +5,7 @@ package pgupgrade import ( - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/controller/pgupgrade/pgupgrade_controller.go b/internal/controller/pgupgrade/pgupgrade_controller.go index 4c2ba30724..07853c56ce 100644 --- a/internal/controller/pgupgrade/pgupgrade_controller.go +++ b/internal/controller/pgupgrade/pgupgrade_controller.go @@ -21,10 +21,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/registration" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/registration" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/controller/pgupgrade/registration.go b/internal/controller/pgupgrade/registration.go index 4d24e1debb..9ead3141f2 100644 --- a/internal/controller/pgupgrade/registration.go +++ b/internal/controller/pgupgrade/registration.go @@ -7,8 +7,8 @@ package pgupgrade import ( "k8s.io/apimachinery/pkg/api/meta" - "github.com/percona/percona-postgresql-operator/internal/registration" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/registration" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func (r *PGUpgradeReconciler) UpgradeAuthorized(upgrade *v1beta1.PGUpgrade) bool { diff --git a/internal/controller/pgupgrade/registration_test.go b/internal/controller/pgupgrade/registration_test.go index 82b583f69e..a8c2af6cca 100644 --- a/internal/controller/pgupgrade/registration_test.go +++ b/internal/controller/pgupgrade/registration_test.go @@ -13,11 +13,11 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/registration" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/events" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/registration" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestUpgradeAuthorized(t *testing.T) { diff --git a/internal/controller/pgupgrade/utils.go b/internal/controller/pgupgrade/utils.go index fddd12a76d..43c033095b 100644 --- a/internal/controller/pgupgrade/utils.go +++ b/internal/controller/pgupgrade/utils.go @@ -12,8 +12,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // The owner reference created by controllerutil.SetControllerReference blocks diff --git a/internal/controller/pgupgrade/world.go b/internal/controller/pgupgrade/world.go index e38c8bea82..e1b451687d 100644 --- a/internal/controller/pgupgrade/world.go +++ b/internal/controller/pgupgrade/world.go @@ -15,7 +15,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // The client used by the controller sets up a cache and an informer for any GVK diff --git a/internal/controller/pgupgrade/world_test.go b/internal/controller/pgupgrade/world_test.go index 71ec5e5828..e4fc2dffb0 100644 --- a/internal/controller/pgupgrade/world_test.go +++ b/internal/controller/pgupgrade/world_test.go @@ -14,9 +14,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPopulateCluster(t *testing.T) { diff --git a/internal/controller/postgrescluster/apply.go b/internal/controller/postgrescluster/apply.go index 33bf0cd9ca..a923856e66 100644 --- a/internal/controller/postgrescluster/apply.go +++ b/internal/controller/postgrescluster/apply.go @@ -12,7 +12,7 @@ import ( "k8s.io/apimachinery/pkg/api/equality" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/kubeapi" + "github.com/percona/percona-postgresql-operator/v2/internal/kubeapi" ) // apply sends an apply patch to object's endpoint in the Kubernetes API and diff --git a/internal/controller/postgrescluster/apply_test.go b/internal/controller/postgrescluster/apply_test.go index 639458bd9d..b7e788c2ce 100644 --- a/internal/controller/postgrescluster/apply_test.go +++ b/internal/controller/postgrescluster/apply_test.go @@ -24,7 +24,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) func TestServerSideApply(t *testing.T) { diff --git a/internal/controller/postgrescluster/cluster.go b/internal/controller/postgrescluster/cluster.go index 7bacd68ed0..e550139fe3 100644 --- a/internal/controller/postgrescluster/cluster.go +++ b/internal/controller/postgrescluster/cluster.go @@ -15,12 +15,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/patroni" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/patroni" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="",resources="configmaps",verbs={create,patch} diff --git a/internal/controller/postgrescluster/cluster_test.go b/internal/controller/postgrescluster/cluster_test.go index 5186bda145..8165d0354f 100644 --- a/internal/controller/postgrescluster/cluster_test.go +++ b/internal/controller/postgrescluster/cluster_test.go @@ -20,12 +20,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var gvks = []runtime.GVK{{ diff --git a/internal/controller/postgrescluster/controller.go b/internal/controller/postgrescluster/controller.go index 12b806b5e0..2dac82621a 100644 --- a/internal/controller/postgrescluster/controller.go +++ b/internal/controller/postgrescluster/controller.go @@ -32,22 +32,22 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgaudit" - "github.com/percona/percona-postgresql-operator/internal/pgbackrest" - "github.com/percona/percona-postgresql-operator/internal/pgbouncer" - "github.com/percona/percona-postgresql-operator/internal/pgmonitor" - "github.com/percona/percona-postgresql-operator/internal/pgstatmonitor" - "github.com/percona/percona-postgresql-operator/internal/pgstatstatements" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/pmm" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/internal/registration" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgaudit" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbouncer" + "github.com/percona/percona-postgresql-operator/v2/internal/pgmonitor" + "github.com/percona/percona-postgresql-operator/v2/internal/pgstatmonitor" + "github.com/percona/percona-postgresql-operator/v2/internal/pgstatstatements" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/pmm" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/registration" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/controller/postgrescluster/controller_ref_manager.go b/internal/controller/postgrescluster/controller_ref_manager.go index ec15ec364a..7eb929b5bd 100644 --- a/internal/controller/postgrescluster/controller_ref_manager.go +++ b/internal/controller/postgrescluster/controller_ref_manager.go @@ -17,10 +17,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/kubeapi" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/kubeapi" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // adoptObject adopts the provided Object by adding controller owner refs for the provided diff --git a/internal/controller/postgrescluster/controller_ref_manager_test.go b/internal/controller/postgrescluster/controller_ref_manager_test.go index 3355936718..10d5c0798e 100644 --- a/internal/controller/postgrescluster/controller_ref_manager_test.go +++ b/internal/controller/postgrescluster/controller_ref_manager_test.go @@ -13,8 +13,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) func TestManageControllerRefs(t *testing.T) { diff --git a/internal/controller/postgrescluster/controller_test.go b/internal/controller/postgrescluster/controller_test.go index 2bd0bef761..e31169f4f7 100644 --- a/internal/controller/postgrescluster/controller_test.go +++ b/internal/controller/postgrescluster/controller_test.go @@ -29,10 +29,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/registration" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/registration" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestDeleteControlled(t *testing.T) { diff --git a/internal/controller/postgrescluster/delete.go b/internal/controller/postgrescluster/delete.go index 95246475f5..5bf1350a94 100644 --- a/internal/controller/postgrescluster/delete.go +++ b/internal/controller/postgrescluster/delete.go @@ -12,8 +12,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="postgres-operator.crunchydata.com",resources="postgresclusters",verbs={patch} diff --git a/internal/controller/postgrescluster/helpers_test.go b/internal/controller/postgrescluster/helpers_test.go index 9ba3519509..22660be30d 100644 --- a/internal/controller/postgrescluster/helpers_test.go +++ b/internal/controller/postgrescluster/helpers_test.go @@ -20,11 +20,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var ( diff --git a/internal/controller/postgrescluster/instance.go b/internal/controller/postgrescluster/instance.go index eab8d75cb6..b80da339d8 100644 --- a/internal/controller/postgrescluster/instance.go +++ b/internal/controller/postgrescluster/instance.go @@ -26,18 +26,18 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/patroni" - "github.com/percona/percona-postgresql-operator/internal/pgbackrest" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/percona/k8s" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/patroni" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/percona/k8s" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // Instance represents a single PostgreSQL instance of a PostgresCluster. diff --git a/internal/controller/postgrescluster/instance_rollout_test.go b/internal/controller/postgrescluster/instance_rollout_test.go index d2cb1605de..197b474d0b 100644 --- a/internal/controller/postgrescluster/instance_rollout_test.go +++ b/internal/controller/postgrescluster/instance_rollout_test.go @@ -23,10 +23,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestReconcilerRolloutInstance(t *testing.T) { diff --git a/internal/controller/postgrescluster/instance_test.go b/internal/controller/postgrescluster/instance_test.go index 17799ee6fb..e2811f1fee 100644 --- a/internal/controller/postgrescluster/instance_test.go +++ b/internal/controller/postgrescluster/instance_test.go @@ -34,14 +34,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/events" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestInstanceIsRunning(t *testing.T) { diff --git a/internal/controller/postgrescluster/patroni.go b/internal/controller/postgrescluster/patroni.go index 802a49369c..49faa501fb 100644 --- a/internal/controller/postgrescluster/patroni.go +++ b/internal/controller/postgrescluster/patroni.go @@ -16,13 +16,13 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/patroni" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/patroni" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="",resources="endpoints",verbs={deletecollection} diff --git a/internal/controller/postgrescluster/patroni_test.go b/internal/controller/postgrescluster/patroni_test.go index 3892e2dacd..6fafaa0595 100644 --- a/internal/controller/postgrescluster/patroni_test.go +++ b/internal/controller/postgrescluster/patroni_test.go @@ -24,11 +24,11 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGeneratePatroniLeaderLeaseService(t *testing.T) { diff --git a/internal/controller/postgrescluster/pgadmin.go b/internal/controller/postgrescluster/pgadmin.go index 091b894788..b60d4dc50a 100644 --- a/internal/controller/postgrescluster/pgadmin.go +++ b/internal/controller/postgrescluster/pgadmin.go @@ -18,13 +18,13 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgadmin" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgadmin" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // reconcilePGAdmin writes the objects necessary to run a pgAdmin Pod. diff --git a/internal/controller/postgrescluster/pgadmin_test.go b/internal/controller/postgrescluster/pgadmin_test.go index 62b7be81e7..e3a5ea54b5 100644 --- a/internal/controller/postgrescluster/pgadmin_test.go +++ b/internal/controller/postgrescluster/pgadmin_test.go @@ -21,11 +21,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGeneratePGAdminConfigMap(t *testing.T) { diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 4144318f9c..19c34e035a 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -29,20 +29,20 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/patroni" - "github.com/percona/percona-postgresql-operator/internal/pgbackrest" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/percona/k8s" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/patroni" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/percona/k8s" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/controller/postgrescluster/pgbackrest_test.go b/internal/controller/postgrescluster/pgbackrest_test.go index 170f704dfd..8d345b38ef 100644 --- a/internal/controller/postgrescluster/pgbackrest_test.go +++ b/internal/controller/postgrescluster/pgbackrest_test.go @@ -36,15 +36,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgbackrest" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var testCronSchedule string = "*/15 * * * *" diff --git a/internal/controller/postgrescluster/pgbouncer.go b/internal/controller/postgrescluster/pgbouncer.go index 3dd963f77a..a7fea64bca 100644 --- a/internal/controller/postgrescluster/pgbouncer.go +++ b/internal/controller/postgrescluster/pgbouncer.go @@ -18,13 +18,13 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgbouncer" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbouncer" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // reconcilePGBouncer writes the objects necessary to run a PgBouncer Pod. diff --git a/internal/controller/postgrescluster/pgbouncer_test.go b/internal/controller/postgrescluster/pgbouncer_test.go index 9424604f70..c40e50971d 100644 --- a/internal/controller/postgrescluster/pgbouncer_test.go +++ b/internal/controller/postgrescluster/pgbouncer_test.go @@ -19,11 +19,11 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGeneratePGBouncerService(t *testing.T) { diff --git a/internal/controller/postgrescluster/pgmonitor.go b/internal/controller/postgrescluster/pgmonitor.go index c8b3d400ba..f8187d1838 100644 --- a/internal/controller/postgrescluster/pgmonitor.go +++ b/internal/controller/postgrescluster/pgmonitor.go @@ -15,16 +15,16 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgmonitor" - "github.com/percona/percona-postgresql-operator/internal/postgres" - pgpassword "github.com/percona/percona-postgresql-operator/internal/postgres/password" - "github.com/percona/percona-postgresql-operator/internal/util" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgmonitor" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + pgpassword "github.com/percona/percona-postgresql-operator/v2/internal/postgres/password" + "github.com/percona/percona-postgresql-operator/v2/internal/util" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // If pgMonitor is enabled the pgMonitor sidecar(s) have been added to the diff --git a/internal/controller/postgrescluster/pgmonitor_test.go b/internal/controller/postgrescluster/pgmonitor_test.go index b38d874ae7..9b738686fd 100644 --- a/internal/controller/postgrescluster/pgmonitor_test.go +++ b/internal/controller/postgrescluster/pgmonitor_test.go @@ -20,12 +20,12 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func testExporterCollectorsAnnotation(t *testing.T, ctx context.Context, cluster *v1beta1.PostgresCluster, queriesConfig, webConfig *corev1.ConfigMap) { diff --git a/internal/controller/postgrescluster/pki.go b/internal/controller/postgrescluster/pki.go index 2568712983..03a8bc200d 100644 --- a/internal/controller/postgrescluster/pki.go +++ b/internal/controller/postgrescluster/pki.go @@ -15,9 +15,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/controller/postgrescluster/pki_test.go b/internal/controller/postgrescluster/pki_test.go index eabdd683ff..cb6228a1bc 100644 --- a/internal/controller/postgrescluster/pki_test.go +++ b/internal/controller/postgrescluster/pki_test.go @@ -19,10 +19,10 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // TestReconcileCerts tests the proper reconciliation of the root ca certificate diff --git a/internal/controller/postgrescluster/pod_disruption_budget.go b/internal/controller/postgrescluster/pod_disruption_budget.go index 8823998ab0..9dc4eab21f 100644 --- a/internal/controller/postgrescluster/pod_disruption_budget.go +++ b/internal/controller/postgrescluster/pod_disruption_budget.go @@ -15,8 +15,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // generatePodDisruptionBudget takes parameters required to fill out a PDB and diff --git a/internal/controller/postgrescluster/pod_disruption_budget_test.go b/internal/controller/postgrescluster/pod_disruption_budget_test.go index 523e4b7da2..6bda5ec1ef 100644 --- a/internal/controller/postgrescluster/pod_disruption_budget_test.go +++ b/internal/controller/postgrescluster/pod_disruption_budget_test.go @@ -12,9 +12,9 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGeneratePodDisruptionBudget(t *testing.T) { diff --git a/internal/controller/postgrescluster/postgres.go b/internal/controller/postgrescluster/postgres.go index fff61cf07c..cafc01fe11 100644 --- a/internal/controller/postgrescluster/postgres.go +++ b/internal/controller/postgrescluster/postgres.go @@ -28,20 +28,20 @@ import ( "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgaudit" - "github.com/percona/percona-postgresql-operator/internal/pgrepack" - "github.com/percona/percona-postgresql-operator/internal/pgstatmonitor" - "github.com/percona/percona-postgresql-operator/internal/pgstatstatements" - "github.com/percona/percona-postgresql-operator/internal/pgvector" - "github.com/percona/percona-postgresql-operator/internal/postgis" - "github.com/percona/percona-postgresql-operator/internal/postgres" - pgpassword "github.com/percona/percona-postgresql-operator/internal/postgres/password" - "github.com/percona/percona-postgresql-operator/internal/util" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgaudit" + "github.com/percona/percona-postgresql-operator/v2/internal/pgrepack" + "github.com/percona/percona-postgresql-operator/v2/internal/pgstatmonitor" + "github.com/percona/percona-postgresql-operator/v2/internal/pgstatstatements" + "github.com/percona/percona-postgresql-operator/v2/internal/pgvector" + "github.com/percona/percona-postgresql-operator/v2/internal/postgis" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + pgpassword "github.com/percona/percona-postgresql-operator/v2/internal/postgres/password" + "github.com/percona/percona-postgresql-operator/v2/internal/util" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // generatePostgresUserSecret returns a Secret containing a password and diff --git a/internal/controller/postgrescluster/postgres_test.go b/internal/controller/postgrescluster/postgres_test.go index 48fc672a34..6b41278bc1 100644 --- a/internal/controller/postgrescluster/postgres_test.go +++ b/internal/controller/postgrescluster/postgres_test.go @@ -23,16 +23,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/events" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGeneratePostgresUserSecret(t *testing.T) { diff --git a/internal/controller/postgrescluster/rbac.go b/internal/controller/postgrescluster/rbac.go index df5dfd0bbe..c90878faf8 100644 --- a/internal/controller/postgrescluster/rbac.go +++ b/internal/controller/postgrescluster/rbac.go @@ -11,10 +11,10 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/patroni" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/patroni" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // reconcileRBACResources creates Roles, RoleBindings, and ServiceAccounts for diff --git a/internal/controller/postgrescluster/snapshots.go b/internal/controller/postgrescluster/snapshots.go index e3c9be0792..cc64aad4e7 100644 --- a/internal/controller/postgrescluster/snapshots.go +++ b/internal/controller/postgrescluster/snapshots.go @@ -18,13 +18,13 @@ import ( volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgbackrest" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="snapshot.storage.k8s.io",resources="volumesnapshots",verbs={get,list,create,patch,delete} diff --git a/internal/controller/postgrescluster/snapshots_test.go b/internal/controller/postgrescluster/snapshots_test.go index 702046e258..dddd6bbb4d 100644 --- a/internal/controller/postgrescluster/snapshots_test.go +++ b/internal/controller/postgrescluster/snapshots_test.go @@ -22,14 +22,14 @@ import ( "k8s.io/utils/ptr" // K8SPG-714 "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/events" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestReconcileVolumeSnapshots(t *testing.T) { diff --git a/internal/controller/postgrescluster/suite_test.go b/internal/controller/postgrescluster/suite_test.go index 99f779a345..1e0d828ee1 100644 --- a/internal/controller/postgrescluster/suite_test.go +++ b/internal/controller/postgrescluster/suite_test.go @@ -22,8 +22,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) var suite struct { diff --git a/internal/controller/postgrescluster/topology_test.go b/internal/controller/postgrescluster/topology_test.go index 5da8c0e7ef..da0933e2e5 100644 --- a/internal/controller/postgrescluster/topology_test.go +++ b/internal/controller/postgrescluster/topology_test.go @@ -10,7 +10,7 @@ import ( "gotest.tools/v3/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) func TestDefaultTopologySpreadConstraints(t *testing.T) { diff --git a/internal/controller/postgrescluster/util.go b/internal/controller/postgrescluster/util.go index 3631a74857..22f391e857 100644 --- a/internal/controller/postgrescluster/util.go +++ b/internal/controller/postgrescluster/util.go @@ -15,9 +15,9 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/rand" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var tmpDirSizeLimit = resource.MustParse("16Mi") diff --git a/internal/controller/postgrescluster/util_test.go b/internal/controller/postgrescluster/util_test.go index 3e673c02d6..efcc9335c8 100644 --- a/internal/controller/postgrescluster/util_test.go +++ b/internal/controller/postgrescluster/util_test.go @@ -15,9 +15,9 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestSafeHash32(t *testing.T) { diff --git a/internal/controller/postgrescluster/volumes.go b/internal/controller/postgrescluster/volumes.go index 16d975c096..a9ec99b8ff 100644 --- a/internal/controller/postgrescluster/volumes.go +++ b/internal/controller/postgrescluster/volumes.go @@ -20,12 +20,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgbackrest" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="",resources="persistentvolumeclaims",verbs={list} diff --git a/internal/controller/postgrescluster/volumes_test.go b/internal/controller/postgrescluster/volumes_test.go index 4de564c810..5dc456fb21 100644 --- a/internal/controller/postgrescluster/volumes_test.go +++ b/internal/controller/postgrescluster/volumes_test.go @@ -20,13 +20,13 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/events" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestHandlePersistentVolumeClaimError(t *testing.T) { diff --git a/internal/controller/postgrescluster/watches.go b/internal/controller/postgrescluster/watches.go index 047903c2ff..d5c37df570 100644 --- a/internal/controller/postgrescluster/watches.go +++ b/internal/controller/postgrescluster/watches.go @@ -13,8 +13,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/patroni" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/patroni" ) // watchPods returns a handler.EventHandler for Pods. diff --git a/internal/controller/runtime/conversion_test.go b/internal/controller/runtime/conversion_test.go index f43a34d989..1e167645e1 100644 --- a/internal/controller/runtime/conversion_test.go +++ b/internal/controller/runtime/conversion_test.go @@ -10,7 +10,7 @@ import ( "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" ) func TestConvertUnstructured(t *testing.T) { diff --git a/internal/controller/runtime/runtime.go b/internal/controller/runtime/runtime.go index 65f06eb43c..d0226ac18e 100644 --- a/internal/controller/runtime/runtime.go +++ b/internal/controller/runtime/runtime.go @@ -18,8 +18,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager/signals" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type ( diff --git a/internal/controller/standalone_pgadmin/configmap.go b/internal/controller/standalone_pgadmin/configmap.go index 2e1390a666..0a277ddcc4 100644 --- a/internal/controller/standalone_pgadmin/configmap.go +++ b/internal/controller/standalone_pgadmin/configmap.go @@ -16,9 +16,9 @@ import ( "github.com/pkg/errors" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="",resources="configmaps",verbs={get} diff --git a/internal/controller/standalone_pgadmin/configmap_test.go b/internal/controller/standalone_pgadmin/configmap_test.go index 3c0fd7eb2d..9d54aa7063 100644 --- a/internal/controller/standalone_pgadmin/configmap_test.go +++ b/internal/controller/standalone_pgadmin/configmap_test.go @@ -9,9 +9,9 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGenerateConfig(t *testing.T) { diff --git a/internal/controller/standalone_pgadmin/controller.go b/internal/controller/standalone_pgadmin/controller.go index f94000f440..49d220710d 100644 --- a/internal/controller/standalone_pgadmin/controller.go +++ b/internal/controller/standalone_pgadmin/controller.go @@ -17,9 +17,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - controllerruntime "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + controllerruntime "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // PGAdminReconciler reconciles a PGAdmin object diff --git a/internal/controller/standalone_pgadmin/controller_test.go b/internal/controller/standalone_pgadmin/controller_test.go index 1c4924dc7a..805d65dac1 100644 --- a/internal/controller/standalone_pgadmin/controller_test.go +++ b/internal/controller/standalone_pgadmin/controller_test.go @@ -14,8 +14,8 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestDeleteControlled(t *testing.T) { diff --git a/internal/controller/standalone_pgadmin/helpers_test.go b/internal/controller/standalone_pgadmin/helpers_test.go index cea3facd87..a4d9201639 100644 --- a/internal/controller/standalone_pgadmin/helpers_test.go +++ b/internal/controller/standalone_pgadmin/helpers_test.go @@ -15,7 +15,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) // Scale extends d according to PGO_TEST_TIMEOUT_SCALE. diff --git a/internal/controller/standalone_pgadmin/helpers_unit_test.go b/internal/controller/standalone_pgadmin/helpers_unit_test.go index a57674e00a..98e311838a 100644 --- a/internal/controller/standalone_pgadmin/helpers_unit_test.go +++ b/internal/controller/standalone_pgadmin/helpers_unit_test.go @@ -9,8 +9,8 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // TODO(benjaminjb): This file is duplicated test help functions diff --git a/internal/controller/standalone_pgadmin/pod.go b/internal/controller/standalone_pgadmin/pod.go index 7c04c72b8d..03dffe698d 100644 --- a/internal/controller/standalone_pgadmin/pod.go +++ b/internal/controller/standalone_pgadmin/pod.go @@ -12,10 +12,10 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/controller/standalone_pgadmin/pod_test.go b/internal/controller/standalone_pgadmin/pod_test.go index f19a08dd56..0e177ec47f 100644 --- a/internal/controller/standalone_pgadmin/pod_test.go +++ b/internal/controller/standalone_pgadmin/pod_test.go @@ -12,9 +12,9 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPod(t *testing.T) { diff --git a/internal/controller/standalone_pgadmin/postgrescluster.go b/internal/controller/standalone_pgadmin/postgrescluster.go index b777140faf..05f15afcce 100644 --- a/internal/controller/standalone_pgadmin/postgrescluster.go +++ b/internal/controller/standalone_pgadmin/postgrescluster.go @@ -11,8 +11,8 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) //+kubebuilder:rbac:groups="postgres-operator.crunchydata.com",resources="pgadmins",verbs={list} diff --git a/internal/controller/standalone_pgadmin/service.go b/internal/controller/standalone_pgadmin/service.go index 74a21deffd..b2e16bf53b 100644 --- a/internal/controller/standalone_pgadmin/service.go +++ b/internal/controller/standalone_pgadmin/service.go @@ -17,9 +17,9 @@ import ( "github.com/pkg/errors" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="",resources="services",verbs={get} diff --git a/internal/controller/standalone_pgadmin/service_test.go b/internal/controller/standalone_pgadmin/service_test.go index d385b6dbc5..0f937af383 100644 --- a/internal/controller/standalone_pgadmin/service_test.go +++ b/internal/controller/standalone_pgadmin/service_test.go @@ -9,8 +9,8 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestService(t *testing.T) { diff --git a/internal/controller/standalone_pgadmin/statefulset.go b/internal/controller/standalone_pgadmin/statefulset.go index 917d615a4a..f377c7b025 100644 --- a/internal/controller/standalone_pgadmin/statefulset.go +++ b/internal/controller/standalone_pgadmin/statefulset.go @@ -15,9 +15,9 @@ import ( "github.com/pkg/errors" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // reconcilePGAdminStatefulSet writes the StatefulSet that runs pgAdmin. diff --git a/internal/controller/standalone_pgadmin/statefulset_test.go b/internal/controller/standalone_pgadmin/statefulset_test.go index 5326366771..9eab30ab10 100644 --- a/internal/controller/standalone_pgadmin/statefulset_test.go +++ b/internal/controller/standalone_pgadmin/statefulset_test.go @@ -14,11 +14,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestReconcilePGAdminStatefulSet(t *testing.T) { diff --git a/internal/controller/standalone_pgadmin/users.go b/internal/controller/standalone_pgadmin/users.go index 0ab1093f8d..db0c9dacd8 100644 --- a/internal/controller/standalone_pgadmin/users.go +++ b/internal/controller/standalone_pgadmin/users.go @@ -18,9 +18,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type Executor func( diff --git a/internal/controller/standalone_pgadmin/users_test.go b/internal/controller/standalone_pgadmin/users_test.go index ce18ddd426..3d575e8b40 100644 --- a/internal/controller/standalone_pgadmin/users_test.go +++ b/internal/controller/standalone_pgadmin/users_test.go @@ -19,11 +19,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/events" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestReconcilePGAdminUsers(t *testing.T) { diff --git a/internal/controller/standalone_pgadmin/volume.go b/internal/controller/standalone_pgadmin/volume.go index 631efce9b0..c5d3c51e31 100644 --- a/internal/controller/standalone_pgadmin/volume.go +++ b/internal/controller/standalone_pgadmin/volume.go @@ -15,8 +15,8 @@ import ( "github.com/pkg/errors" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:groups="",resources="persistentvolumeclaims",verbs={create,patch} diff --git a/internal/controller/standalone_pgadmin/volume_test.go b/internal/controller/standalone_pgadmin/volume_test.go index 8103943dd8..724d1cb4e1 100644 --- a/internal/controller/standalone_pgadmin/volume_test.go +++ b/internal/controller/standalone_pgadmin/volume_test.go @@ -17,13 +17,13 @@ import ( "k8s.io/apimachinery/pkg/util/validation/field" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/events" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestReconcilePGAdminDataVolume(t *testing.T) { diff --git a/internal/controller/standalone_pgadmin/watches.go b/internal/controller/standalone_pgadmin/watches.go index 0632961abe..99232690a7 100644 --- a/internal/controller/standalone_pgadmin/watches.go +++ b/internal/controller/standalone_pgadmin/watches.go @@ -14,7 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // watchPostgresClusters returns a [handler.EventHandler] for PostgresClusters. diff --git a/internal/controller/standalone_pgadmin/watches_test.go b/internal/controller/standalone_pgadmin/watches_test.go index 88a21e07b5..8313a6d5e5 100644 --- a/internal/controller/standalone_pgadmin/watches_test.go +++ b/internal/controller/standalone_pgadmin/watches_test.go @@ -12,8 +12,8 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestFindPGAdminsForSecret(t *testing.T) { diff --git a/internal/initialize/intstr_test.go b/internal/initialize/intstr_test.go index 4b877980e9..998161bf50 100644 --- a/internal/initialize/intstr_test.go +++ b/internal/initialize/intstr_test.go @@ -21,7 +21,7 @@ import ( "gotest.tools/v3/assert" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" ) func TestIntOrStringInt32(t *testing.T) { diff --git a/internal/initialize/metadata_test.go b/internal/initialize/metadata_test.go index 6704e4c11d..1ad4016d10 100644 --- a/internal/initialize/metadata_test.go +++ b/internal/initialize/metadata_test.go @@ -10,7 +10,7 @@ import ( "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" ) func TestAnnotations(t *testing.T) { diff --git a/internal/initialize/primitives_test.go b/internal/initialize/primitives_test.go index ed3aaa504a..8e2c372e3f 100644 --- a/internal/initialize/primitives_test.go +++ b/internal/initialize/primitives_test.go @@ -9,7 +9,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" ) func TestBool(t *testing.T) { diff --git a/internal/initialize/security_test.go b/internal/initialize/security_test.go index 909b8d3443..8a684e3ada 100644 --- a/internal/initialize/security_test.go +++ b/internal/initialize/security_test.go @@ -11,7 +11,7 @@ import ( "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" ) func TestPodSecurityContext(t *testing.T) { diff --git a/internal/naming/names.go b/internal/naming/names.go index d5da45b024..74f484c54d 100644 --- a/internal/naming/names.go +++ b/internal/naming/names.go @@ -13,8 +13,8 @@ import ( "k8s.io/apimachinery/pkg/util/rand" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/naming/names_test.go b/internal/naming/names_test.go index a1b1c7df48..bf2c8bd43c 100644 --- a/internal/naming/names_test.go +++ b/internal/naming/names_test.go @@ -15,7 +15,7 @@ import ( "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestAsObjectKey(t *testing.T) { diff --git a/internal/naming/selectors.go b/internal/naming/selectors.go index 5f662a39e9..9911bc82ae 100644 --- a/internal/naming/selectors.go +++ b/internal/naming/selectors.go @@ -8,7 +8,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // AsSelector is a wrapper around metav1.LabelSelectorAsSelector() which converts diff --git a/internal/naming/selectors_test.go b/internal/naming/selectors_test.go index e4651d9778..f036900ce5 100644 --- a/internal/naming/selectors_test.go +++ b/internal/naming/selectors_test.go @@ -10,7 +10,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestAnyCluster(t *testing.T) { diff --git a/internal/naming/telemetry.go b/internal/naming/telemetry.go index 351f52f4ec..82bf0dcee3 100644 --- a/internal/naming/telemetry.go +++ b/internal/naming/telemetry.go @@ -6,4 +6,4 @@ package naming import "go.opentelemetry.io/otel" -var tracer = otel.Tracer("github.com/percona/percona-postgresql-operator/naming") +var tracer = otel.Tracer("github.com/percona/percona-postgresql-operator/v2/naming") diff --git a/internal/patroni/api.go b/internal/patroni/api.go index af9d9739ec..e3c7803720 100644 --- a/internal/patroni/api.go +++ b/internal/patroni/api.go @@ -12,7 +12,7 @@ import ( "io" "strings" - "github.com/percona/percona-postgresql-operator/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" ) // API defines a general interface for interacting with the Patroni API. diff --git a/internal/patroni/certificates_test.go b/internal/patroni/certificates_test.go index 3432db41e8..49aa72dba0 100644 --- a/internal/patroni/certificates_test.go +++ b/internal/patroni/certificates_test.go @@ -11,7 +11,7 @@ import ( "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) type funcMarshaler func() ([]byte, error) diff --git a/internal/patroni/config.go b/internal/patroni/config.go index 80beafd095..b7431591a5 100644 --- a/internal/patroni/config.go +++ b/internal/patroni/config.go @@ -12,10 +12,10 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/patroni/config_test.go b/internal/patroni/config_test.go index 4209cc0781..710704424f 100644 --- a/internal/patroni/config_test.go +++ b/internal/patroni/config_test.go @@ -17,12 +17,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestClusterYAML(t *testing.T) { diff --git a/internal/patroni/rbac.go b/internal/patroni/rbac.go index 617323acb8..3c74a074e7 100644 --- a/internal/patroni/rbac.go +++ b/internal/patroni/rbac.go @@ -8,7 +8,7 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // "list", "patch", and "watch" are required. Include "get" for good measure. diff --git a/internal/patroni/rbac_test.go b/internal/patroni/rbac_test.go index 0bef7b4904..22cc67a9c5 100644 --- a/internal/patroni/rbac_test.go +++ b/internal/patroni/rbac_test.go @@ -10,8 +10,8 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func isUniqueAndSorted(slice []string) bool { diff --git a/internal/patroni/reconcile.go b/internal/patroni/reconcile.go index 276a6fcc17..5399ddfdf6 100644 --- a/internal/patroni/reconcile.go +++ b/internal/patroni/reconcile.go @@ -12,14 +12,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pgbackrest" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/percona/k8s" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/percona/k8s" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // ClusterBootstrapped returns a bool indicating whether or not Patroni has successfully diff --git a/internal/patroni/reconcile_test.go b/internal/patroni/reconcile_test.go index 419b74ab09..8c9238738a 100644 --- a/internal/patroni/reconcile_test.go +++ b/internal/patroni/reconcile_test.go @@ -12,11 +12,11 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestClusterConfigMap(t *testing.T) { diff --git a/internal/pgadmin/config.go b/internal/pgadmin/config.go index f7169b69e0..3b5d7518ea 100644 --- a/internal/pgadmin/config.go +++ b/internal/pgadmin/config.go @@ -9,7 +9,7 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/pgadmin/config_test.go b/internal/pgadmin/config_test.go index f25ddbcaff..837429bd91 100644 --- a/internal/pgadmin/config_test.go +++ b/internal/pgadmin/config_test.go @@ -14,9 +14,9 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPodConfigFiles(t *testing.T) { diff --git a/internal/pgadmin/reconcile.go b/internal/pgadmin/reconcile.go index 5a46258551..795b828666 100644 --- a/internal/pgadmin/reconcile.go +++ b/internal/pgadmin/reconcile.go @@ -12,10 +12,10 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // startupScript is the script for the configuration and startup of the pgAdmin service. diff --git a/internal/pgadmin/reconcile_test.go b/internal/pgadmin/reconcile_test.go index 5e9e051c0b..e8fd612d2c 100644 --- a/internal/pgadmin/reconcile_test.go +++ b/internal/pgadmin/reconcile_test.go @@ -12,9 +12,9 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestConfigMap(t *testing.T) { diff --git a/internal/pgadmin/users.go b/internal/pgadmin/users.go index 659bb92b85..b391f98d88 100644 --- a/internal/pgadmin/users.go +++ b/internal/pgadmin/users.go @@ -12,9 +12,9 @@ import ( "io" "strings" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type Executor func( diff --git a/internal/pgadmin/users_test.go b/internal/pgadmin/users_test.go index 89904ec8ba..64a7c412e3 100644 --- a/internal/pgadmin/users_test.go +++ b/internal/pgadmin/users_test.go @@ -17,9 +17,9 @@ import ( "gotest.tools/v3/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestWriteUsersInPGAdmin(t *testing.T) { diff --git a/internal/pgaudit/postgres.go b/internal/pgaudit/postgres.go index d6d7710935..b4c5df8313 100644 --- a/internal/pgaudit/postgres.go +++ b/internal/pgaudit/postgres.go @@ -7,8 +7,8 @@ package pgaudit import ( "context" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) // When the pgAudit shared library is not loaded, the extension cannot be diff --git a/internal/pgaudit/postgres_test.go b/internal/pgaudit/postgres_test.go index ce869e88ff..b3d1332cb8 100644 --- a/internal/pgaudit/postgres_test.go +++ b/internal/pgaudit/postgres_test.go @@ -13,7 +13,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) func TestEnableInPostgreSQL(t *testing.T) { diff --git a/internal/pgbackrest/certificates.go b/internal/pgbackrest/certificates.go index c734b475fc..fda8ae768d 100644 --- a/internal/pgbackrest/certificates.go +++ b/internal/pgbackrest/certificates.go @@ -10,7 +10,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" ) const ( diff --git a/internal/pgbackrest/certificates_test.go b/internal/pgbackrest/certificates_test.go index a6f6d8c7c5..2a96b03690 100644 --- a/internal/pgbackrest/certificates_test.go +++ b/internal/pgbackrest/certificates_test.go @@ -13,7 +13,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) type funcMarshaler func() ([]byte, error) diff --git a/internal/pgbackrest/config.go b/internal/pgbackrest/config.go index 9909754204..eecae059ac 100644 --- a/internal/pgbackrest/config.go +++ b/internal/pgbackrest/config.go @@ -14,11 +14,11 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/pgbackrest/config_test.go b/internal/pgbackrest/config_test.go index bc69f564b6..766c6812f3 100644 --- a/internal/pgbackrest/config_test.go +++ b/internal/pgbackrest/config_test.go @@ -16,11 +16,11 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestCreatePGBackRestConfigMapIntent(t *testing.T) { diff --git a/internal/pgbackrest/helpers_test.go b/internal/pgbackrest/helpers_test.go index e4b2e51a73..189b4311f7 100644 --- a/internal/pgbackrest/helpers_test.go +++ b/internal/pgbackrest/helpers_test.go @@ -16,7 +16,7 @@ package pgbackrest import ( - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) // marshalMatches converts actual to YAML and compares that to expected. diff --git a/internal/pgbackrest/pgbackrest.go b/internal/pgbackrest/pgbackrest.go index 618fa850d3..07cc075ceb 100644 --- a/internal/pgbackrest/pgbackrest.go +++ b/internal/pgbackrest/pgbackrest.go @@ -12,7 +12,7 @@ import ( "github.com/pkg/errors" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/pgbackrest/pgbackrest_test.go b/internal/pgbackrest/pgbackrest_test.go index 4c5c901120..c6bd43d0db 100644 --- a/internal/pgbackrest/pgbackrest_test.go +++ b/internal/pgbackrest/pgbackrest_test.go @@ -16,8 +16,8 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestStanzaCreateOrUpgrade(t *testing.T) { diff --git a/internal/pgbackrest/postgres.go b/internal/pgbackrest/postgres.go index a8bce592fa..71f6e3167a 100644 --- a/internal/pgbackrest/postgres.go +++ b/internal/pgbackrest/postgres.go @@ -7,8 +7,8 @@ package pgbackrest import ( "strings" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // PostgreSQL populates outParameters with any settings needed to run pgBackRest. diff --git a/internal/pgbackrest/postgres_test.go b/internal/pgbackrest/postgres_test.go index 48ce0e5e0b..6572e35113 100644 --- a/internal/pgbackrest/postgres_test.go +++ b/internal/pgbackrest/postgres_test.go @@ -10,8 +10,8 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPostgreSQLParameters(t *testing.T) { diff --git a/internal/pgbackrest/rbac.go b/internal/pgbackrest/rbac.go index dfc842dc9f..6febd5ca2d 100644 --- a/internal/pgbackrest/rbac.go +++ b/internal/pgbackrest/rbac.go @@ -8,7 +8,7 @@ import ( corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // +kubebuilder:rbac:namespace=pgbackrest,groups="",resources="pods",verbs={list} diff --git a/internal/pgbackrest/rbac_test.go b/internal/pgbackrest/rbac_test.go index 8cc4ee3617..2d0fcf7f7b 100644 --- a/internal/pgbackrest/rbac_test.go +++ b/internal/pgbackrest/rbac_test.go @@ -10,8 +10,8 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func isUniqueAndSorted(slice []string) bool { diff --git a/internal/pgbackrest/reconcile.go b/internal/pgbackrest/reconcile.go index 8d2b831dc2..e301618cc9 100644 --- a/internal/pgbackrest/reconcile.go +++ b/internal/pgbackrest/reconcile.go @@ -12,13 +12,13 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // AddRepoVolumesToPod adds pgBackRest repository volumes to the provided Pod template spec, while diff --git a/internal/pgbackrest/reconcile_test.go b/internal/pgbackrest/reconcile_test.go index 1ceaade9b9..fc5eee5ba6 100644 --- a/internal/pgbackrest/reconcile_test.go +++ b/internal/pgbackrest/reconcile_test.go @@ -17,11 +17,11 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestAddRepoVolumesToPod(t *testing.T) { diff --git a/internal/pgbackrest/util.go b/internal/pgbackrest/util.go index 8f4725e648..31ac33f0cc 100644 --- a/internal/pgbackrest/util.go +++ b/internal/pgbackrest/util.go @@ -12,7 +12,7 @@ import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/util/rand" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // maxPGBackrestRepos is the maximum number of repositories that can be configured according to the diff --git a/internal/pgbackrest/util_test.go b/internal/pgbackrest/util_test.go index fb18e2b676..b7ae94810f 100644 --- a/internal/pgbackrest/util_test.go +++ b/internal/pgbackrest/util_test.go @@ -13,7 +13,7 @@ import ( "gotest.tools/v3/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestCalculateConfigHashes(t *testing.T) { diff --git a/internal/pgbouncer/assertions_test.go b/internal/pgbouncer/assertions_test.go index 49def23334..3561bef782 100644 --- a/internal/pgbouncer/assertions_test.go +++ b/internal/pgbouncer/assertions_test.go @@ -16,7 +16,7 @@ package pgbouncer import ( - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) // marshalMatches converts actual to YAML and compares that to expected. diff --git a/internal/pgbouncer/certificates_test.go b/internal/pgbouncer/certificates_test.go index 5c4a461205..94757456c7 100644 --- a/internal/pgbouncer/certificates_test.go +++ b/internal/pgbouncer/certificates_test.go @@ -10,7 +10,7 @@ import ( "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) func TestBackendAuthority(t *testing.T) { diff --git a/internal/pgbouncer/config.go b/internal/pgbouncer/config.go index d7615c4b6f..ef5803361b 100644 --- a/internal/pgbouncer/config.go +++ b/internal/pgbouncer/config.go @@ -11,8 +11,8 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/pgbouncer/config_test.go b/internal/pgbouncer/config_test.go index 04f9a204e7..e57b6d103d 100644 --- a/internal/pgbouncer/config_test.go +++ b/internal/pgbouncer/config_test.go @@ -17,9 +17,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPrettyYAML(t *testing.T) { diff --git a/internal/pgbouncer/postgres.go b/internal/pgbouncer/postgres.go index 4f9a651238..6e3ccd9ed7 100644 --- a/internal/pgbouncer/postgres.go +++ b/internal/pgbouncer/postgres.go @@ -10,10 +10,10 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/internal/postgres/password" - "github.com/percona/percona-postgresql-operator/internal/util" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres/password" + "github.com/percona/percona-postgresql-operator/v2/internal/util" ) const ( diff --git a/internal/pgbouncer/reconcile.go b/internal/pgbouncer/reconcile.go index 835d6f157e..8c0e92fdd6 100644 --- a/internal/pgbouncer/reconcile.go +++ b/internal/pgbouncer/reconcile.go @@ -11,13 +11,13 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // ConfigMap populates the PgBouncer ConfigMap. diff --git a/internal/pgbouncer/reconcile_test.go b/internal/pgbouncer/reconcile_test.go index a8c70a9335..989ead0b67 100644 --- a/internal/pgbouncer/reconcile_test.go +++ b/internal/pgbouncer/reconcile_test.go @@ -13,12 +13,12 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/pki" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/pki" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestConfigMap(t *testing.T) { diff --git a/internal/pgmonitor/api.go b/internal/pgmonitor/api.go index 11a794b917..2037b5f8c7 100644 --- a/internal/pgmonitor/api.go +++ b/internal/pgmonitor/api.go @@ -22,7 +22,7 @@ import ( "io" "strings" - "github.com/percona/percona-postgresql-operator/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" ) type Executor func( diff --git a/internal/pgmonitor/exporter.go b/internal/pgmonitor/exporter.go index fd873523bd..1e1d04aef4 100644 --- a/internal/pgmonitor/exporter.go +++ b/internal/pgmonitor/exporter.go @@ -10,8 +10,8 @@ import ( "os" "strings" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/pgmonitor/exporter_test.go b/internal/pgmonitor/exporter_test.go index de43451c88..8e3c54e991 100644 --- a/internal/pgmonitor/exporter_test.go +++ b/internal/pgmonitor/exporter_test.go @@ -13,8 +13,8 @@ import ( "gotest.tools/v3/assert" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGenerateDefaultExporterQueries(t *testing.T) { diff --git a/internal/pgmonitor/postgres.go b/internal/pgmonitor/postgres.go index 6af8515e9d..64053fc1fe 100644 --- a/internal/pgmonitor/postgres.go +++ b/internal/pgmonitor/postgres.go @@ -9,9 +9,9 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/pgmonitor/postgres_test.go b/internal/pgmonitor/postgres_test.go index f27a6e04a8..bb58746c54 100644 --- a/internal/pgmonitor/postgres_test.go +++ b/internal/pgmonitor/postgres_test.go @@ -10,8 +10,8 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPostgreSQLHBA(t *testing.T) { diff --git a/internal/pgmonitor/util.go b/internal/pgmonitor/util.go index a31efeb58e..cb0e5b453e 100644 --- a/internal/pgmonitor/util.go +++ b/internal/pgmonitor/util.go @@ -8,8 +8,8 @@ import ( "context" "os" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func GetQueriesConfigDir(ctx context.Context) string { diff --git a/internal/pgmonitor/util_test.go b/internal/pgmonitor/util_test.go index 2d1957aa54..087572cda7 100644 --- a/internal/pgmonitor/util_test.go +++ b/internal/pgmonitor/util_test.go @@ -9,7 +9,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestExporterEnabled(t *testing.T) { diff --git a/internal/pgrepack/postgres.go b/internal/pgrepack/postgres.go index 16fd7104b9..401ca692ce 100644 --- a/internal/pgrepack/postgres.go +++ b/internal/pgrepack/postgres.go @@ -3,8 +3,8 @@ package pgrepack import ( "context" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) // EnableInPostgreSQL installs pg_repack triggers into every database. diff --git a/internal/pgstatmonitor/pgstatmonitor.go b/internal/pgstatmonitor/pgstatmonitor.go index 103ff31375..5a2d67840f 100644 --- a/internal/pgstatmonitor/pgstatmonitor.go +++ b/internal/pgstatmonitor/pgstatmonitor.go @@ -4,8 +4,8 @@ import ( "context" "strings" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) func EnableInPostgreSQL(ctx context.Context, exec postgres.Executor) error { diff --git a/internal/pgstatmonitor/pgstatmonitor_test.go b/internal/pgstatmonitor/pgstatmonitor_test.go index 193f75c76a..c191a55773 100644 --- a/internal/pgstatmonitor/pgstatmonitor_test.go +++ b/internal/pgstatmonitor/pgstatmonitor_test.go @@ -9,7 +9,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) func TestEnableInPostgreSQL(t *testing.T) { diff --git a/internal/pgstatstatements/pgstatstatement.go b/internal/pgstatstatements/pgstatstatement.go index dcea8ea565..3a2e42ec6c 100644 --- a/internal/pgstatstatements/pgstatstatement.go +++ b/internal/pgstatstatements/pgstatstatement.go @@ -3,8 +3,8 @@ package pgstatstatements import ( "context" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) func EnableInPostgreSQL(ctx context.Context, exec postgres.Executor) error { diff --git a/internal/pgstatstatements/pgstatstatement_test.go b/internal/pgstatstatements/pgstatstatement_test.go index 1c81be5e30..a3b454ceb2 100644 --- a/internal/pgstatstatements/pgstatstatement_test.go +++ b/internal/pgstatstatements/pgstatstatement_test.go @@ -9,7 +9,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) func TestEnableInPostgreSQL(t *testing.T) { diff --git a/internal/pgvector/postgres.go b/internal/pgvector/postgres.go index 13b7ae0ebe..ba3122a03e 100644 --- a/internal/pgvector/postgres.go +++ b/internal/pgvector/postgres.go @@ -3,8 +3,8 @@ package pgvector import ( "context" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) // EnableInPostgreSQL installs pgvector triggers into every database. diff --git a/internal/pki/encoding_test.go b/internal/pki/encoding_test.go index e1edc773d4..837e4f38e7 100644 --- a/internal/pki/encoding_test.go +++ b/internal/pki/encoding_test.go @@ -14,7 +14,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) func TestCertificateTextMarshaling(t *testing.T) { diff --git a/internal/pki/pki_test.go b/internal/pki/pki_test.go index efa3db8395..2eb5633961 100644 --- a/internal/pki/pki_test.go +++ b/internal/pki/pki_test.go @@ -16,7 +16,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) type StringSet map[string]struct{} diff --git a/internal/pmm/hba.go b/internal/pmm/hba.go index 1afea911ee..ff9838c435 100644 --- a/internal/pmm/hba.go +++ b/internal/pmm/hba.go @@ -1,8 +1,8 @@ package pmm import ( - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/postgis/postgis.go b/internal/postgis/postgis.go index 2b8732ca39..7b54a06395 100644 --- a/internal/postgis/postgis.go +++ b/internal/postgis/postgis.go @@ -8,8 +8,8 @@ import ( "context" "strings" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" ) // EnableInPostgreSQL installs triggers for the following extensions into every database: diff --git a/internal/postgres/assertions_test.go b/internal/postgres/assertions_test.go index 24d5f5e789..4f4054d9d1 100644 --- a/internal/postgres/assertions_test.go +++ b/internal/postgres/assertions_test.go @@ -16,7 +16,7 @@ package postgres import ( - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) func marshalMatches(actual interface{}, expected string) cmp.Comparison { diff --git a/internal/postgres/config.go b/internal/postgres/config.go index e71ccc37ab..1ac7b38a86 100644 --- a/internal/postgres/config.go +++ b/internal/postgres/config.go @@ -11,10 +11,10 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/postgres/config_test.go b/internal/postgres/config_test.go index af625fdb66..e449443b93 100644 --- a/internal/postgres/config_test.go +++ b/internal/postgres/config_test.go @@ -19,9 +19,9 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestConfigDirectory(t *testing.T) { diff --git a/internal/postgres/databases.go b/internal/postgres/databases.go index e03e0b9056..f6ddf8a17a 100644 --- a/internal/postgres/databases.go +++ b/internal/postgres/databases.go @@ -9,7 +9,7 @@ import ( "context" "encoding/json" - "github.com/percona/percona-postgresql-operator/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" ) // CreateDatabasesInPostgreSQL calls exec to create databases that do not exist diff --git a/internal/postgres/databases_test.go b/internal/postgres/databases_test.go index fd9939f2f8..faff8efb4b 100644 --- a/internal/postgres/databases_test.go +++ b/internal/postgres/databases_test.go @@ -13,7 +13,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) func TestCreateDatabasesInPostgreSQL(t *testing.T) { diff --git a/internal/postgres/exec_test.go b/internal/postgres/exec_test.go index 3101017b99..405ce5ffbc 100644 --- a/internal/postgres/exec_test.go +++ b/internal/postgres/exec_test.go @@ -16,7 +16,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" ) // This example demonstrates how Executor can work with exec.Cmd. diff --git a/internal/postgres/hba_test.go b/internal/postgres/hba_test.go index 34469a7f13..1ae97f9c04 100644 --- a/internal/postgres/hba_test.go +++ b/internal/postgres/hba_test.go @@ -10,7 +10,7 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) func TestNewHBAs(t *testing.T) { diff --git a/internal/postgres/huge_pages.go b/internal/postgres/huge_pages.go index 05f0cc8e51..ab78ef53ca 100644 --- a/internal/postgres/huge_pages.go +++ b/internal/postgres/huge_pages.go @@ -8,7 +8,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // This function looks for a valid huge_pages resource request. If it finds one, diff --git a/internal/postgres/huge_pages_test.go b/internal/postgres/huge_pages_test.go index 2478099e05..0b4505c57f 100644 --- a/internal/postgres/huge_pages_test.go +++ b/internal/postgres/huge_pages_test.go @@ -11,8 +11,8 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestSetHugePages(t *testing.T) { diff --git a/internal/postgres/reconcile.go b/internal/postgres/reconcile.go index d1c66fce44..ab17fb59d3 100644 --- a/internal/postgres/reconcile.go +++ b/internal/postgres/reconcile.go @@ -10,11 +10,11 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var ( diff --git a/internal/postgres/reconcile_test.go b/internal/postgres/reconcile_test.go index 7cfe249fc0..17da5bf3ff 100644 --- a/internal/postgres/reconcile_test.go +++ b/internal/postgres/reconcile_test.go @@ -12,12 +12,12 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/percona/version" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestDataVolumeMount(t *testing.T) { diff --git a/internal/postgres/users.go b/internal/postgres/users.go index 52b7e861cb..80fd4261ec 100644 --- a/internal/postgres/users.go +++ b/internal/postgres/users.go @@ -13,10 +13,10 @@ import ( pg_query "github.com/pganalyze/pg_query_go/v6" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var RESERVED_SCHEMA_NAMES = map[string]bool{ diff --git a/internal/postgres/users_test.go b/internal/postgres/users_test.go index f132c6f8c1..7481ab6080 100644 --- a/internal/postgres/users_test.go +++ b/internal/postgres/users_test.go @@ -14,8 +14,8 @@ import ( "gotest.tools/v3/assert" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestSanitizeAlterRoleOptions(t *testing.T) { diff --git a/internal/registration/interface.go b/internal/registration/interface.go index 2e4d8a9c3a..8f1a4a3477 100644 --- a/internal/registration/interface.go +++ b/internal/registration/interface.go @@ -14,7 +14,7 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type Registration interface { diff --git a/internal/registration/runner.go b/internal/registration/runner.go index eb5bfe576e..7ef4fbfe18 100644 --- a/internal/registration/runner.go +++ b/internal/registration/runner.go @@ -20,8 +20,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // Runner implements [Registration] by loading and validating the token at a diff --git a/internal/registration/runner_test.go b/internal/registration/runner_test.go index b46f04909f..1143667746 100644 --- a/internal/registration/runner_test.go +++ b/internal/registration/runner_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/testing/events" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/events" ) func TestNewRunner(t *testing.T) { diff --git a/internal/testing/require/kubernetes.go b/internal/testing/require/kubernetes.go index c8e6d61127..cab581ec76 100644 --- a/internal/testing/require/kubernetes.go +++ b/internal/testing/require/kubernetes.go @@ -19,7 +19,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" ) type TestingT interface { diff --git a/internal/testing/validation/postgrescluster_test.go b/internal/testing/validation/postgrescluster_test.go index a411424bcb..5062e0719b 100644 --- a/internal/testing/validation/postgrescluster_test.go +++ b/internal/testing/validation/postgrescluster_test.go @@ -14,9 +14,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPostgresUserOptions(t *testing.T) { diff --git a/internal/upgradecheck/header.go b/internal/upgradecheck/header.go index b418691a9b..2b886385d8 100644 --- a/internal/upgradecheck/header.go +++ b/internal/upgradecheck/header.go @@ -18,11 +18,11 @@ import ( "k8s.io/client-go/rest" crclient "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/internal/upgradecheck/header_test.go b/internal/upgradecheck/header_test.go index 995a9a2768..dc100294d3 100644 --- a/internal/upgradecheck/header_test.go +++ b/internal/upgradecheck/header_test.go @@ -20,12 +20,12 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "k8s.io/client-go/rest" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" - "github.com/percona/percona-postgresql-operator/internal/testing/require" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/require" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestGenerateHeader(t *testing.T) { diff --git a/internal/upgradecheck/helpers_test.go b/internal/upgradecheck/helpers_test.go index e687569e7f..845d6bbe37 100644 --- a/internal/upgradecheck/helpers_test.go +++ b/internal/upgradecheck/helpers_test.go @@ -20,9 +20,9 @@ import ( crclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type fakeClientWithError struct { diff --git a/internal/upgradecheck/http.go b/internal/upgradecheck/http.go index 0de194245e..2d4e2c65ea 100644 --- a/internal/upgradecheck/http.go +++ b/internal/upgradecheck/http.go @@ -17,7 +17,7 @@ import ( crclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" ) var ( diff --git a/internal/upgradecheck/http_test.go b/internal/upgradecheck/http_test.go index c50b92c41e..85762e7e40 100644 --- a/internal/upgradecheck/http_test.go +++ b/internal/upgradecheck/http_test.go @@ -21,9 +21,9 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/testing/cmp" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/testing/cmp" ) func init() { diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index be38cd09e8..3e5311ffe7 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -23,15 +23,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/percona/clientcmd" - "github.com/percona/percona-postgresql-operator/percona/controller" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/pgbackrest" - "github.com/percona/percona-postgresql-operator/percona/watcher" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/clientcmd" + "github.com/percona/percona-postgresql-operator/v2/percona/controller" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/pgbackrest" + "github.com/percona/percona-postgresql-operator/v2/percona/watcher" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/percona/controller/pgbackup/controller_test.go b/percona/controller/pgbackup/controller_test.go index bcb13bf8b1..6edd3f8590 100644 --- a/percona/controller/pgbackup/controller_test.go +++ b/percona/controller/pgbackup/controller_test.go @@ -8,10 +8,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/naming" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestFailIfClusterIsNotReady(t *testing.T) { diff --git a/percona/controller/pgbackup/testutils_test.go b/percona/controller/pgbackup/testutils_test.go index 897b557909..a7d7a7394d 100644 --- a/percona/controller/pgbackup/testutils_test.go +++ b/percona/controller/pgbackup/testutils_test.go @@ -11,10 +11,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/percona/percona-postgresql-operator/internal/naming" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type fakeClient struct { diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 5b432283e5..61835badec 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -12,12 +12,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/percona/controller" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/pgbackrest" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/controller" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/pgbackrest" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) func (r *PGClusterReconciler) reconcileBackups(ctx context.Context, cr *v2.PerconaPGCluster) error { diff --git a/percona/controller/pgcluster/backup_test.go b/percona/controller/pgcluster/backup_test.go index a4abf6d55d..d4a4f92dcb 100644 --- a/percona/controller/pgcluster/backup_test.go +++ b/percona/controller/pgcluster/backup_test.go @@ -14,9 +14,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func compareMaps(x map[string]string, y map[string]string) bool { diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 4ef3d379cc..0400522404 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -38,23 +38,23 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" - "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/internal/postgres" - "github.com/percona/percona-postgresql-operator/percona/clientcmd" - perconaController "github.com/percona/percona-postgresql-operator/percona/controller" - "github.com/percona/percona-postgresql-operator/percona/extensions" - "github.com/percona/percona-postgresql-operator/percona/k8s" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/pmm" - perconaPG "github.com/percona/percona-postgresql-operator/percona/postgres" - "github.com/percona/percona-postgresql-operator/percona/utils/registry" - "github.com/percona/percona-postgresql-operator/percona/version" - "github.com/percona/percona-postgresql-operator/percona/watcher" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/percona/clientcmd" + perconaController "github.com/percona/percona-postgresql-operator/v2/percona/controller" + "github.com/percona/percona-postgresql-operator/v2/percona/extensions" + "github.com/percona/percona-postgresql-operator/v2/percona/k8s" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/pmm" + perconaPG "github.com/percona/percona-postgresql-operator/v2/percona/postgres" + "github.com/percona/percona-postgresql-operator/v2/percona/utils/registry" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + "github.com/percona/percona-postgresql-operator/v2/percona/watcher" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 3f5bba0ade..a6d5574669 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -24,12 +24,12 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/naming" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/version" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var _ = Describe("PG Cluster", Ordered, func() { diff --git a/percona/controller/pgcluster/finalizer.go b/percona/controller/pgcluster/finalizer.go index 5ab625cada..1f6805ba5a 100644 --- a/percona/controller/pgcluster/finalizer.go +++ b/percona/controller/pgcluster/finalizer.go @@ -13,11 +13,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/percona/controller" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/controller" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) type finalizerFunc func(context.Context, *v2.PerconaPGCluster) error diff --git a/percona/controller/pgcluster/finalizer_test.go b/percona/controller/pgcluster/finalizer_test.go index de9f3f218b..4b2e19ba8c 100644 --- a/percona/controller/pgcluster/finalizer_test.go +++ b/percona/controller/pgcluster/finalizer_test.go @@ -19,9 +19,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var _ = Describe("Finalizers", Ordered, func() { diff --git a/percona/controller/pgcluster/restore.go b/percona/controller/pgcluster/restore.go index e8c4e2f8b6..d941aa05b5 100644 --- a/percona/controller/pgcluster/restore.go +++ b/percona/controller/pgcluster/restore.go @@ -6,9 +6,9 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/internal/naming" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) // createBootstrapRestoreObject creates a PerconaPGRestore object for the bootstrap restore diff --git a/percona/controller/pgcluster/schedule.go b/percona/controller/pgcluster/schedule.go index 4515380cf7..ad5d65412f 100644 --- a/percona/controller/pgcluster/schedule.go +++ b/percona/controller/pgcluster/schedule.go @@ -10,12 +10,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func (r *PGClusterReconciler) reconcileScheduledBackups(ctx context.Context, cr *v2.PerconaPGCluster) error { diff --git a/percona/controller/pgcluster/secret.go b/percona/controller/pgcluster/secret.go index 302894ff34..109332e9ce 100644 --- a/percona/controller/pgcluster/secret.go +++ b/percona/controller/pgcluster/secret.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) func getEnvFromSecrets(ctx context.Context, cl client.Client, cr *v2.PerconaPGCluster, envFromSource []corev1.EnvFromSource) ([]corev1.Secret, error) { diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index 2589a26e35..d0491462db 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -9,10 +9,10 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func (r *PGClusterReconciler) getHost(ctx context.Context, cr *v2.PerconaPGCluster) (string, error) { diff --git a/percona/controller/pgcluster/status_test.go b/percona/controller/pgcluster/status_test.go index 2b08dc7c0a..ea9ed9ed68 100644 --- a/percona/controller/pgcluster/status_test.go +++ b/percona/controller/pgcluster/status_test.go @@ -17,10 +17,10 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var _ = Describe("PG Cluster status", Ordered, func() { diff --git a/percona/controller/pgcluster/suite_test.go b/percona/controller/pgcluster/suite_test.go index 4316600709..19d7ad4ed8 100644 --- a/percona/controller/pgcluster/suite_test.go +++ b/percona/controller/pgcluster/suite_test.go @@ -20,8 +20,8 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to diff --git a/percona/controller/pgcluster/testutils_test.go b/percona/controller/pgcluster/testutils_test.go index 21b8771a32..7dcb1dc001 100644 --- a/percona/controller/pgcluster/testutils_test.go +++ b/percona/controller/pgcluster/testutils_test.go @@ -18,14 +18,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/event" - "github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/percona/controller/pgbackup" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/utils/registry" - "github.com/percona/percona-postgresql-operator/percona/watcher" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgbackup" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/utils/registry" + "github.com/percona/percona-postgresql-operator/v2/percona/watcher" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) var k8sClient client.Client diff --git a/percona/controller/pgcluster/version.go b/percona/controller/pgcluster/version.go index 04be089232..b45dbacb86 100644 --- a/percona/controller/pgcluster/version.go +++ b/percona/controller/pgcluster/version.go @@ -11,11 +11,11 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/percona/extensions" - "github.com/percona/percona-postgresql-operator/percona/k8s" - "github.com/percona/percona-postgresql-operator/percona/version" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/percona/extensions" + "github.com/percona/percona-postgresql-operator/v2/percona/k8s" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) func (r *PGClusterReconciler) reconcileVersion(ctx context.Context, cr *v2.PerconaPGCluster) error { diff --git a/percona/controller/pgcluster/version_test.go b/percona/controller/pgcluster/version_test.go index 324ced2236..3c5327749d 100644 --- a/percona/controller/pgcluster/version_test.go +++ b/percona/controller/pgcluster/version_test.go @@ -25,8 +25,8 @@ import ( "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" - "github.com/percona/percona-postgresql-operator/percona/version" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) var _ = Describe("Ensure Version", Ordered, func() { diff --git a/percona/controller/pgrestore/controller.go b/percona/controller/pgrestore/controller.go index db249f05ab..0061744463 100644 --- a/percona/controller/pgrestore/controller.go +++ b/percona/controller/pgrestore/controller.go @@ -16,12 +16,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/percona/controller" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/controller" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( diff --git a/percona/controller/pgupgrade/controller.go b/percona/controller/pgupgrade/controller.go index 1f82b929fc..06746159f0 100644 --- a/percona/controller/pgupgrade/controller.go +++ b/percona/controller/pgupgrade/controller.go @@ -16,11 +16,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/percona/extensions" - pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/percona/extensions" + pgv2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( @@ -35,7 +34,7 @@ type PGUpgradeReconciler struct { // SetupWithManager adds the PerconaPerconaPGUpgrade controller to the provided runtime manager func (r *PGUpgradeReconciler) SetupWithManager(mgr manager.Manager) error { - return builder.ControllerManagedBy(mgr).For(&v2.PerconaPGUpgrade{}).Complete(r) + return builder.ControllerManagedBy(mgr).For(&pgv2.PerconaPGUpgrade{}).Complete(r) } // +kubebuilder:rbac:groups=pgv2.percona.com,resources=perconapgupgrades,verbs=get;list;create;update;patch;watch diff --git a/percona/controller/utils.go b/percona/controller/utils.go index 6f0a509cae..28a6582716 100644 --- a/percona/controller/utils.go +++ b/percona/controller/utils.go @@ -11,8 +11,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" ) // jobCompleted returns "true" if the Job provided completed successfully. Otherwise it returns diff --git a/percona/extensions/containers.go b/percona/extensions/containers.go index eba068ae79..a3d695f18b 100644 --- a/percona/extensions/containers.go +++ b/percona/extensions/containers.go @@ -6,8 +6,8 @@ import ( corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/percona/naming" - pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/percona/naming" + pgv2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) func GetExtensionKey(pgMajor int, name, version string) string { diff --git a/percona/k8s/testutils_test.go b/percona/k8s/testutils_test.go index 3ce9f33c57..ca2eb465a2 100644 --- a/percona/k8s/testutils_test.go +++ b/percona/k8s/testutils_test.go @@ -13,10 +13,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/percona/percona-postgresql-operator/internal/naming" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type fakeClient struct { diff --git a/percona/k8s/util.go b/percona/k8s/util.go index 3133d9df4e..18f4b36e34 100644 --- a/percona/k8s/util.go +++ b/percona/k8s/util.go @@ -16,9 +16,9 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/version" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const WatchNamespaceEnvVar = "WATCH_NAMESPACE" diff --git a/percona/k8s/util_test.go b/percona/k8s/util_test.go index 1c27d26275..a78e94b941 100644 --- a/percona/k8s/util_test.go +++ b/percona/k8s/util_test.go @@ -12,7 +12,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) type testGetCluster func() *v1beta1.PostgresCluster diff --git a/percona/pgbackrest/pgbackrest.go b/percona/pgbackrest/pgbackrest.go index d71cecb89c..0e5dd872eb 100644 --- a/percona/pgbackrest/pgbackrest.go +++ b/percona/pgbackrest/pgbackrest.go @@ -10,9 +10,9 @@ import ( "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" - "github.com/percona/percona-postgresql-operator/internal/naming" - "github.com/percona/percona-postgresql-operator/percona/clientcmd" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/clientcmd" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) type InfoOutput []InfoStanza diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index 7a52ce467d..c6d45b2831 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -7,7 +7,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) const ( diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index 03b3561ab5..738cd79a10 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -10,8 +10,8 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/percona/percona-postgresql-operator/percona/version" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) func TestContainer(t *testing.T) { diff --git a/percona/postgres/common.go b/percona/postgres/common.go index b1d8c35837..2f9ba62cfc 100644 --- a/percona/postgres/common.go +++ b/percona/postgres/common.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" - v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGCluster) (*corev1.Pod, error) { diff --git a/percona/runtime/runtime.go b/percona/runtime/runtime.go index cc2df3e008..147474aebf 100644 --- a/percona/runtime/runtime.go +++ b/percona/runtime/runtime.go @@ -9,10 +9,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/manager" - r "github.com/percona/percona-postgresql-operator/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/internal/feature" - "github.com/percona/percona-postgresql-operator/internal/initialize" - "github.com/percona/percona-postgresql-operator/percona/k8s" + r "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/percona/k8s" ) // default refresh interval in minutes diff --git a/percona/testutils/client.go b/percona/testutils/client.go index 6288e69e9a..242ef3ba0c 100644 --- a/percona/testutils/client.go +++ b/percona/testutils/client.go @@ -5,8 +5,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" - crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + pgv2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func BuildFakeClient(initObjs ...client.Object) client.Client { diff --git a/percona/version/service/client/api_version_proto_client.go b/percona/version/service/client/api_version_proto_client.go index 82aeb57415..5b524bd421 100644 --- a/percona/version/service/client/api_version_proto_client.go +++ b/percona/version/service/client/api_version_proto_client.go @@ -10,7 +10,7 @@ import ( httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" - "github.com/percona/percona-postgresql-operator/percona/version/service/client/version_service" + "github.com/percona/percona-postgresql-operator/v2/percona/version/service/client/version_service" ) // Default API version proto HTTP client. diff --git a/percona/version/service/client/version_service/version_service_apply_responses.go b/percona/version/service/client/version_service/version_service_apply_responses.go index e1357b86bd..5a19d36520 100644 --- a/percona/version/service/client/version_service/version_service_apply_responses.go +++ b/percona/version/service/client/version_service/version_service_apply_responses.go @@ -12,7 +12,7 @@ import ( "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" - "github.com/percona/percona-postgresql-operator/percona/version/service/client/models" + "github.com/percona/percona-postgresql-operator/v2/percona/version/service/client/models" ) // VersionServiceApplyReader is a Reader for the VersionServiceApply structure. diff --git a/percona/version/service/client/version_service/version_service_operator_responses.go b/percona/version/service/client/version_service/version_service_operator_responses.go index dd5449f1a8..5625dae723 100644 --- a/percona/version/service/client/version_service/version_service_operator_responses.go +++ b/percona/version/service/client/version_service/version_service_operator_responses.go @@ -12,7 +12,7 @@ import ( "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" - "github.com/percona/percona-postgresql-operator/percona/version/service/client/models" + "github.com/percona/percona-postgresql-operator/v2/percona/version/service/client/models" ) // VersionServiceOperatorReader is a Reader for the VersionServiceOperator structure. diff --git a/percona/version/service/client/version_service/version_service_product_responses.go b/percona/version/service/client/version_service/version_service_product_responses.go index 8464af47b5..8bd92d59d8 100644 --- a/percona/version/service/client/version_service/version_service_product_responses.go +++ b/percona/version/service/client/version_service/version_service_product_responses.go @@ -12,7 +12,7 @@ import ( "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" - "github.com/percona/percona-postgresql-operator/percona/version/service/client/models" + "github.com/percona/percona-postgresql-operator/v2/percona/version/service/client/models" ) // VersionServiceProductReader is a Reader for the VersionServiceProduct structure. diff --git a/percona/version/version.go b/percona/version/version.go index 85f61bc83d..b2d566008c 100644 --- a/percona/version/version.go +++ b/percona/version/version.go @@ -12,8 +12,8 @@ import ( "github.com/pkg/errors" - "github.com/percona/percona-postgresql-operator/percona/version/service/client" - "github.com/percona/percona-postgresql-operator/percona/version/service/client/version_service" + "github.com/percona/percona-postgresql-operator/v2/percona/version/service/client" + "github.com/percona/percona-postgresql-operator/v2/percona/version/service/client/version_service" ) //go:generate sh -c "yq -i '.metadata.labels.\"pgv2.percona.com/version\" = \"v\" + load(\"version.txt\")' ../../config/crd/patches/versionlabel_in_perconapgclusters.yaml" diff --git a/percona/version/version_test.go b/percona/version/version_test.go index 6ee19eb059..2a8f172086 100644 --- a/percona/version/version_test.go +++ b/percona/version/version_test.go @@ -11,8 +11,8 @@ import ( "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "sigs.k8s.io/yaml" - "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/version" + "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/version" ) func TestCRDVersionLabel(t *testing.T) { diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index 9946e85751..c2aa12e6b8 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -12,11 +12,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/percona/clientcmd" - "github.com/percona/percona-postgresql-operator/percona/pgbackrest" - perconaPG "github.com/percona/percona-postgresql-operator/percona/postgres" - pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/percona/clientcmd" + "github.com/percona/percona-postgresql-operator/v2/percona/pgbackrest" + perconaPG "github.com/percona/percona-postgresql-operator/v2/percona/postgres" + pgv2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) const ( diff --git a/percona/watcher/wal_test.go b/percona/watcher/wal_test.go index a3dd176652..757bc329f8 100644 --- a/percona/watcher/wal_test.go +++ b/percona/watcher/wal_test.go @@ -11,8 +11,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/percona/percona-postgresql-operator/percona/testutils" - pgv2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/percona/testutils" + pgv2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) func mustParseTime(layout string, value string) time.Time { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go index 5e0fd6d3f1..367b1d7f58 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go @@ -9,7 +9,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func init() { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 2445ce2031..c929b57026 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -11,12 +11,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/percona/percona-postgresql-operator/internal/config" - "github.com/percona/percona-postgresql-operator/internal/logging" - "github.com/percona/percona-postgresql-operator/internal/naming" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" - "github.com/percona/percona-postgresql-operator/percona/version" - crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/config" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func init() { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go index fa43445019..06fefe918d 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go @@ -12,8 +12,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "github.com/percona/percona-postgresql-operator/internal/naming" - crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPerconaPGCluster_Default(t *testing.T) { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go index 9dc99076fe..70943c4dc9 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go @@ -4,7 +4,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - crunchyv1beta1 "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func init() { diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index bfbf0041c2..1409dcf859 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -9,7 +9,7 @@ package v2 import ( - "github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 1fd3fd8d8a..90c93cb978 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -16,7 +16,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" - pNaming "github.com/percona/percona-postgresql-operator/percona/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" ) // PostgresClusterSpec defines the desired state of PostgresCluster From c62817b2f1b27212de1a9c8e97e2470e92f78133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Fri, 10 Oct 2025 11:27:26 +0300 Subject: [PATCH 170/300] K8SPG-844: Don't modify archive_command if trackLatestRestorableTime is disabled (#1290) * K8SPG-844: Don't modify archive_command if trackLatestRestorableTime is disabled * fix * compare version for updating the archive command * param ordering fix * remove unused params * fixes * fix linter --------- Co-authored-by: Viacheslav Sarzhan Co-authored-by: George Kechagias --- ...ator.crunchydata.com_postgresclusters.yaml | 3 + ...ator.crunchydata.com_postgresclusters.yaml | 3 + deploy/bundle.yaml | 3 + deploy/crd.yaml | 3 + deploy/cw-bundle.yaml | 3 + internal/pgbackrest/postgres.go | 38 ++- internal/pgbackrest/postgres_test.go | 242 +++++++++++++----- .../v2/perconapgcluster_types.go | 8 +- .../v2/perconapgcluster_types_test.go | 4 +- .../v1beta1/postgrescluster_types.go | 3 + .../v1beta1/zz_generated.deepcopy.go | 5 + 11 files changed, 234 insertions(+), 81 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 0b69f54392..f43983758c 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -6938,6 +6938,9 @@ spec: required: - volumeSnapshotClassName type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean type: object config: properties: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index a950d40cc9..09005917b5 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -6928,6 +6928,9 @@ spec: required: - volumeSnapshotClassName type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean type: object config: properties: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index d7a01c53c4..cfdd17c835 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -36721,6 +36721,9 @@ spec: required: - volumeSnapshotClassName type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean type: object config: properties: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 2dfe715be9..b815257fd7 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -36721,6 +36721,9 @@ spec: required: - volumeSnapshotClassName type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean type: object config: properties: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 526eb5d9eb..f8f7bbd1e2 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -36721,6 +36721,9 @@ spec: required: - volumeSnapshotClassName type: object + trackLatestRestorableTime: + description: Enable tracking latest restorable time + type: boolean type: object config: properties: diff --git a/internal/pgbackrest/postgres.go b/internal/pgbackrest/postgres.go index 71f6e3167a..50dd2a5d20 100644 --- a/internal/pgbackrest/postgres.go +++ b/internal/pgbackrest/postgres.go @@ -28,13 +28,20 @@ func PostgreSQL( // - https://pgbackrest.org/user-guide.html#quickstart/configure-archiving // - https://pgbackrest.org/command.html#command-archive-push // - https://www.postgresql.org/docs/current/runtime-config-wal.html - - fixTimezone := `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | sed "s/UTC/Z/"` - extractCommitTime := `grep -oP "COMMIT \K[^;]+" | ` + fixTimezone + `` - validateCommitTime := `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"` archive := `pgbackrest --stanza=` + DefaultStanzaName + ` archive-push "%p"` - archive += ` && timestamp=$(pg_waldump "%p" | ` + extractCommitTime + ` | tail -n 1 | ` + validateCommitTime + `);` - archive += ` if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi` + + // K8SPG-518 + if inCluster.CompareVersion("2.8.0") >= 0 { + if trackRestorableTime := inCluster.Spec.Backups.TrackLatestRestorableTime; trackRestorableTime != nil && *trackRestorableTime { + updateCommandRestorableTime(&archive) + // K8SPG-518: This parameter is required to ensure that the commit timestamp is + // included in the WAL file. This is necessary for the WAL watcher to + // function correctly. + outParameters.Mandatory.Add("track_commit_timestamp", "true") + } + } else { + updateCommandRestorableTime(&archive) + } outParameters.Mandatory.Add("archive_mode", "on") @@ -46,10 +53,12 @@ func PostgreSQL( outParameters.Mandatory.Add("archive_command", `true`) } - // K8SPG-518: This parameter is required to ensure that the commit timestamp is - // included in the WAL file. This is necessary for the WAL watcher to - // function correctly. - outParameters.Mandatory.Add("track_commit_timestamp", "true") + if inCluster.CompareVersion("2.8.0") < 0 { + // K8SPG-518: This parameter is required to ensure that the commit timestamp is + // included in the WAL file. This is necessary for the WAL watcher to + // function correctly. + outParameters.Mandatory.Add("track_commit_timestamp", "true") + } // archive_timeout is used to determine at what point a WAL file is switched, // if the WAL archive has not reached its full size in # of transactions @@ -94,3 +103,12 @@ func PostgreSQL( outParameters.Mandatory.Add("restore_command", restore) } } + +func updateCommandRestorableTime(archive *string) { + fixTimezone := `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | sed "s/UTC/Z/"` + extractCommitTime := `grep -oP "COMMIT \K[^;]+" | ` + fixTimezone + `` + validateCommitTime := `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"` + + *archive += ` && timestamp=$(pg_waldump "%p" | ` + extractCommitTime + ` | tail -n 1 | ` + validateCommitTime + `);` + *archive += ` if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi` +} diff --git a/internal/pgbackrest/postgres_test.go b/internal/pgbackrest/postgres_test.go index 6572e35113..c45dd1d2d3 100644 --- a/internal/pgbackrest/postgres_test.go +++ b/internal/pgbackrest/postgres_test.go @@ -9,85 +9,189 @@ import ( "testing" "gotest.tools/v3/assert" + "k8s.io/utils/ptr" "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + "github.com/percona/percona-postgresql-operator/v2/percona/version" "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) func TestPostgreSQLParameters(t *testing.T) { - cluster := new(v1beta1.PostgresCluster) - parameters := new(postgres.Parameters) - - PostgreSQL(cluster, parameters, true) - assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ - "archive_mode": "on", - "archive_command": strings.Join([]string{ - `pgbackrest --stanza=db archive-push "%p" `, - `&& timestamp=$(pg_waldump "%p" | `, - `grep -oP "COMMIT \K[^;]+" | `, - `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, - `sed "s/UTC/Z/" | `, - "tail -n 1 | ", - `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, - "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", - }, ""), - "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, - "track_commit_timestamp": "true", - }) + t.Run("latest CR version", func(t *testing.T) { + cluster := new(v1beta1.PostgresCluster) + parameters := new(postgres.Parameters) - assert.DeepEqual(t, parameters.Default.AsMap(), map[string]string{ - "archive_timeout": "60s", - }) + if cluster.Labels == nil { + cluster.Labels = make(map[string]string) + } + cluster.Labels["pgv2.percona.com/version"] = version.Version() + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": `pgbackrest --stanza=db archive-push "%p"`, + "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, + }) - dynamic := map[string]any{ - "postgresql": map[string]any{ - "parameters": map[string]any{ - "restore_command": "/bin/true", + assert.DeepEqual(t, parameters.Default.AsMap(), map[string]string{ + "archive_timeout": "60s", + }) + + dynamic := map[string]any{ + "postgresql": map[string]any{ + "parameters": map[string]any{ + "restore_command": "/bin/true", + }, }, - }, - } - if cluster.Spec.Patroni == nil { - cluster.Spec.Patroni = &v1beta1.PatroniSpec{} - } - cluster.Spec.Patroni.DynamicConfiguration = dynamic - - PostgreSQL(cluster, parameters, true) - assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ - "archive_mode": "on", - "archive_command": strings.Join([]string{ - `pgbackrest --stanza=db archive-push "%p" `, - `&& timestamp=$(pg_waldump "%p" | `, - `grep -oP "COMMIT \K[^;]+" | `, - `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, - `sed "s/UTC/Z/" | `, - "tail -n 1 | ", - `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, - "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", - }, ""), - "restore_command": "/bin/true", - "track_commit_timestamp": "true", + } + if cluster.Spec.Patroni == nil { + cluster.Spec.Patroni = &v1beta1.PatroniSpec{} + } + cluster.Spec.Patroni.DynamicConfiguration = dynamic + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": `pgbackrest --stanza=db archive-push "%p"`, + "restore_command": "/bin/true", + }) + + cluster.Spec.Standby = &v1beta1.PostgresStandbySpec{ + Enabled: true, + RepoName: "repo99", + } + cluster.Spec.Patroni.DynamicConfiguration = nil + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": `pgbackrest --stanza=db archive-push "%p"`, + "restore_command": `pgbackrest --stanza=db archive-get %f "%p" --repo=99`, + }) + + cluster.Spec.Standby = nil + cluster.Spec.Patroni.DynamicConfiguration = nil + cluster.Spec.Backups.TrackLatestRestorableTime = ptr.To(true) + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": strings.Join([]string{ + `pgbackrest --stanza=db archive-push "%p" `, + `&& timestamp=$(pg_waldump "%p" | `, + `grep -oP "COMMIT \K[^;]+" | `, + `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, + `sed "s/UTC/Z/" | `, + "tail -n 1 | ", + `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, + "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", + }, ""), + "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, + "track_commit_timestamp": "true", + }) }) - cluster.Spec.Standby = &v1beta1.PostgresStandbySpec{ - Enabled: true, - RepoName: "repo99", - } - cluster.Spec.Patroni.DynamicConfiguration = nil - - PostgreSQL(cluster, parameters, true) - assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ - "archive_mode": "on", - "archive_command": strings.Join([]string{ - `pgbackrest --stanza=db archive-push "%p" `, - `&& timestamp=$(pg_waldump "%p" | `, - `grep -oP "COMMIT \K[^;]+" | `, - `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, - `sed "s/UTC/Z/" | `, - "tail -n 1 | ", - `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, - "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", - }, ""), - "restore_command": `pgbackrest --stanza=db archive-get %f "%p" --repo=99`, - "track_commit_timestamp": "true", + t.Run("2.8.0< version", func(t *testing.T) { + cluster := new(v1beta1.PostgresCluster) + parameters := new(postgres.Parameters) + + if cluster.Labels == nil { + cluster.Labels = make(map[string]string) + } + cluster.Labels["pgv2.percona.com/version"] = "2.7.0" + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": strings.Join([]string{ + `pgbackrest --stanza=db archive-push "%p" `, + `&& timestamp=$(pg_waldump "%p" | `, + `grep -oP "COMMIT \K[^;]+" | `, + `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, + `sed "s/UTC/Z/" | `, + "tail -n 1 | ", + `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, + "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", + }, ""), + "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, + "track_commit_timestamp": "true", + }) + + assert.DeepEqual(t, parameters.Default.AsMap(), map[string]string{ + "archive_timeout": "60s", + }) + + dynamic := map[string]any{ + "postgresql": map[string]any{ + "parameters": map[string]any{ + "restore_command": "/bin/true", + }, + }, + } + if cluster.Spec.Patroni == nil { + cluster.Spec.Patroni = &v1beta1.PatroniSpec{} + } + cluster.Spec.Patroni.DynamicConfiguration = dynamic + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": strings.Join([]string{ + `pgbackrest --stanza=db archive-push "%p" `, + `&& timestamp=$(pg_waldump "%p" | `, + `grep -oP "COMMIT \K[^;]+" | `, + `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, + `sed "s/UTC/Z/" | `, + "tail -n 1 | ", + `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, + "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", + }, ""), + "restore_command": "/bin/true", + "track_commit_timestamp": "true", + }) + + cluster.Spec.Standby = &v1beta1.PostgresStandbySpec{ + Enabled: true, + RepoName: "repo99", + } + cluster.Spec.Patroni.DynamicConfiguration = nil + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": strings.Join([]string{ + `pgbackrest --stanza=db archive-push "%p" `, + `&& timestamp=$(pg_waldump "%p" | `, + `grep -oP "COMMIT \K[^;]+" | `, + `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, + `sed "s/UTC/Z/" | `, + "tail -n 1 | ", + `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, + "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", + }, ""), + "restore_command": `pgbackrest --stanza=db archive-get %f "%p" --repo=99`, + "track_commit_timestamp": "true", + }) + + cluster.Spec.Standby = nil + cluster.Spec.Patroni.DynamicConfiguration = nil + cluster.Spec.Backups.TrackLatestRestorableTime = ptr.To(true) + + PostgreSQL(cluster, parameters, true) + assert.DeepEqual(t, parameters.Mandatory.AsMap(), map[string]string{ + "archive_mode": "on", + "archive_command": strings.Join([]string{ + `pgbackrest --stanza=db archive-push "%p" `, + `&& timestamp=$(pg_waldump "%p" | `, + `grep -oP "COMMIT \K[^;]+" | `, + `sed -E "s/([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}) (UTC|[\\+\\-][0-9]{2})/\1T\2\3/" | `, + `sed "s/UTC/Z/" | `, + "tail -n 1 | ", + `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, + "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", + }, ""), + "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, + "track_commit_timestamp": "true", + }) }) } diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index c929b57026..89f3285a0c 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -505,7 +505,7 @@ func (b Backups) ToCrunchy(version string) crunchyv1beta1.Backups { sc = b.PGBackRest.Sidecars } - return crunchyv1beta1.Backups{ + backups := crunchyv1beta1.Backups{ PGBackRest: crunchyv1beta1.PGBackRestArchive{ Metadata: b.PGBackRest.Metadata, Configuration: b.PGBackRest.Configuration, @@ -522,6 +522,12 @@ func (b Backups) ToCrunchy(version string) crunchyv1beta1.Backups { EnvFrom: b.PGBackRest.EnvFrom, }, } + + if currVersion != nil && currVersion.GreaterThanOrEqual(gover.Must(gover.NewVersion("2.8.0"))) { + backups.TrackLatestRestorableTime = b.TrackLatestRestorableTime + } + + return backups } type PGBackRestArchive struct { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go index 06fefe918d..fe0fc77d90 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go @@ -13,6 +13,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/version" crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) @@ -135,7 +136,7 @@ func TestPerconaPGCluster_ToCrunchy(t *testing.T) { Namespace: "test-namespace", }, Spec: PerconaPGClusterSpec{ - CRVersion: "2.8.0", + CRVersion: version.Version(), PostgresVersion: 15, Expose: &ServiceExpose{ Type: "LoadBalancer", @@ -180,6 +181,7 @@ func TestPerconaPGCluster_ToCrunchy(t *testing.T) { assert.Equal(t, actual.Spec.ReplicaService.Type, expected.Spec.ExposeReplicas.Type) assert.Assert(t, actual.Spec.ReplicaService.LoadBalancerClass != nil) assert.Equal(t, actual.Spec.ReplicaService.LoadBalancerClass, expected.Spec.ExposeReplicas.LoadBalancerClass) + assert.Equal(t, *actual.Spec.Backups.TrackLatestRestorableTime, true) }, }, "updates existing PostgresCluster": { diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 90c93cb978..e2a846ceb0 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -365,6 +365,9 @@ type Backups struct { // VolumeSnapshot configuration // +optional Snapshots *VolumeSnapshots `json:"snapshots,omitempty"` + + // Enable tracking latest restorable time + TrackLatestRestorableTime *bool `json:"trackLatestRestorableTime,omitempty"` } // PostgresClusterStatus defines the observed state of PostgresCluster diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 523d8dc6d7..2ef09eb950 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -90,6 +90,11 @@ func (in *Backups) DeepCopyInto(out *Backups) { *out = new(VolumeSnapshots) **out = **in } + if in.TrackLatestRestorableTime != nil { + in, out := &in.TrackLatestRestorableTime, &out.TrackLatestRestorableTime + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backups. From 347501a9072afa4d8366099fc31b37af90afb158 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 10 Oct 2025 12:13:28 +0300 Subject: [PATCH 171/300] K8SPG-624 use bool type for DisableSSL and ForcePathStyle --- .../generated/pgv2.percona.com_perconapgclusters.yaml | 4 ++-- config/crd/bases/pgv2.percona.com_perconapgclusters.yaml | 4 ++-- deploy/bundle.yaml | 4 ++-- deploy/crd.yaml | 4 ++-- deploy/cw-bundle.yaml | 4 ++-- percona/extensions/containers.go | 8 ++++---- pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 3245fe267d..b31dda3640 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -10303,11 +10303,11 @@ spec: bucket: type: string disableSSL: - type: string + type: boolean endpoint: type: string forcePathStyle: - type: string + type: boolean region: type: string secret: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index d5b8c6b285..8b38ce51f4 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -10708,11 +10708,11 @@ spec: bucket: type: string disableSSL: - type: string + type: boolean endpoint: type: string forcePathStyle: - type: string + type: boolean region: type: string secret: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index cfdd17c835..97b02f85f9 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -11005,11 +11005,11 @@ spec: bucket: type: string disableSSL: - type: string + type: boolean endpoint: type: string forcePathStyle: - type: string + type: boolean region: type: string secret: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index b815257fd7..9124e34575 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -11005,11 +11005,11 @@ spec: bucket: type: string disableSSL: - type: string + type: boolean endpoint: type: string forcePathStyle: - type: string + type: boolean region: type: string secret: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index f8f7bbd1e2..8d766bd59c 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -11005,11 +11005,11 @@ spec: bucket: type: string disableSSL: - type: string + type: boolean endpoint: type: string forcePathStyle: - type: string + type: boolean region: type: string secret: diff --git a/percona/extensions/containers.go b/percona/extensions/containers.go index a3d695f18b..7ca5b5a9cb 100644 --- a/percona/extensions/containers.go +++ b/percona/extensions/containers.go @@ -106,17 +106,17 @@ func InstallerContainer(cr *pgv2.PerconaPGCluster, postgresVersion int, spec *pg if cr.CompareVersion("2.8.0") >= 0 { // Check whether the configuration exists so that existing e2e tests // that do not set these values are not affected. - if spec.Storage.DisableSSL != "" { + if spec.Storage.DisableSSL { container.Env = append(container.Env, corev1.EnvVar{ Name: "STORAGE_DISABLE_SSL", - Value: spec.Storage.DisableSSL, + Value: strconv.FormatBool(spec.Storage.DisableSSL), }) } - if spec.Storage.ForcePathStyle != "" { + if spec.Storage.ForcePathStyle { container.Env = append(container.Env, corev1.EnvVar{ Name: "STORAGE_FORCE_PATH_STYLE", - Value: spec.Storage.ForcePathStyle, + Value: strconv.FormatBool(spec.Storage.ForcePathStyle), }) } } diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 89f3285a0c..8b0fb316ec 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -659,8 +659,8 @@ type CustomExtensionsStorageSpec struct { Bucket string `json:"bucket,omitempty"` Region string `json:"region,omitempty"` Endpoint string `json:"endpoint,omitempty"` - ForcePathStyle string `json:"forcePathStyle,omitempty"` - DisableSSL string `json:"disableSSL,omitempty"` + ForcePathStyle bool `json:"forcePathStyle,omitempty"` + DisableSSL bool `json:"disableSSL,omitempty"` Secret *corev1.SecretProjection `json:"secret,omitempty"` } From 9c217f3655a68d017b1cf361c09fca2860dae55f Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 10 Oct 2025 12:34:39 +0300 Subject: [PATCH 172/300] fix e2e test values --- e2e-tests/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 8a11e0fed4..256bde67bf 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -292,7 +292,7 @@ get_cr() { yq eval -i ' .spec.extensions.image = "'$IMAGE'" | .spec.extensions.imagePullPolicy = "Always" | - .spec.extensions.storage = {"type": "s3", "bucket": "operator-testing", "region": "us-east-1", "endpoint": "http://minio-service:9000", "forcePathStyle": "true", "disableSSL": "true", "secret": {"name": "minio-secret"}} + .spec.extensions.storage = {"type": "s3", "bucket": "operator-testing", "region": "us-east-1", "endpoint": "http://minio-service:9000", "forcePathStyle": true, "disableSSL": true, "secret": {"name": "minio-secret"}} ' $TEMP_DIR/cr.yaml ;; esac From 96cd16cac80dde0d1f3c4c42b807d6f735e3ebbf Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Fri, 10 Oct 2025 09:05:39 -0300 Subject: [PATCH 173/300] Fix initContainer images replacement in Makefile release --- Makefile | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 18305d77b8..528b983dbb 100644 --- a/Makefile +++ b/Makefile @@ -448,12 +448,13 @@ PG_VER ?= $(shell grep -o "postgresVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+" include e2e-tests/release_versions release: generate $(SED) -i \ - -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(VERSION)/}" \ - -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_POSTGRESQL17)#}" \ - -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_PGBOUNCER17)#}" \ - -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_BACKREST17)#}" \ - -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_OPERATOR)#}" \ - -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_PMM3_CLIENT)#}" deploy/cr.yaml + -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(VERSION)/}" \ + -e "/^spec:/,/^ image:/{/^#/! s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_POSTGRESQL17)#}" \ + -e "s| image: docker.io/perconalab/percona-postgresql-operator:main| image: $(IMAGE)|" \ + -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_PGBOUNCER17)#}" \ + -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_BACKREST17)#}" \ + -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_OPERATOR)#}" \ + -e "/^ pmm:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_PMM3_CLIENT)#}" deploy/cr.yaml $(SED) -i -r "/Version *= \"[0-9]+\.[0-9]+\.[0-9]+\"$$/ s/[0-9]+\.[0-9]+\.[0-9]+/$(VERSION)/" pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go $(SED) -i \ -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)$(IMAGE_UPGRADE)#}" \ From 8ed702c500fdb7de1fa33953b4045567062f6af9 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Sat, 11 Oct 2025 15:33:39 +0300 Subject: [PATCH 174/300] Fix backup-enable-disable test --- e2e-tests/functions | 58 +++++++++++++++++++ e2e-tests/kuttl.yaml | 2 +- .../03-disable-backups.yaml | 2 + 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 256bde67bf..8c88ffc077 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -115,6 +115,64 @@ remove_all_finalizers() { done } +wait_for_ready_containers() { + local pod_prefix="$1" + local target_count="$2" + local namespace="${NAMESPACE}" + local max_wait_seconds=300 + local check_interval=5 + local elapsed_time=0 + + if [[ -z "$pod_prefix" || -z "$target_count" || -z "$namespace" ]]; then + echo "Error: Missing arguments." >&2 + echo "Usage: wait_for_ready_containers " >&2 + return 1 + fi + + echo "Waiting for pods starting with '$pod_prefix' in namespace '$namespace' to have $target_count ready containers (Max ${max_wait_seconds}s)..." + + while [[ "$elapsed_time" -lt "$max_wait_seconds" ]]; do + local target_pods + # Get pods that match the prefix AND are running + target_pods=$(kubectl get pods -n "$namespace" --field-selector=status.phase=Running --output=json | \ + jq -r ".items[] | select(.metadata.name | startswith(\"$pod_prefix\")) | .metadata.name") + # If no running pods match the prefix, something might be wrong, but we'll keep waiting. + if [[ -z "$target_pods" ]]; then + echo "No running pods found with prefix '$pod_prefix'. Waiting..." + sleep "$check_interval" + elapsed_time=$((elapsed_time + check_interval)) + continue + fi + + local ready_count=0 + local total_matches=0 + + # Check each pod individually + for pod_name in $target_pods; do + total_matches=$((total_matches + 1)) + current_ready=$(kubectl get pod "$pod_name" -n "$namespace" -o json 2>/dev/null | \ + jq '.status.containerStatuses | map(select(.ready == true)) | length') + + if [[ "$current_ready" -eq "$target_count" ]]; then + ready_count=$((ready_count + 1)) + fi + done + + if [[ "$ready_count" -eq "$total_matches" ]]; then + echo "Success: All $total_matches pods now have $target_count ready containers." + return 0 + fi + + echo "Current status: $ready_count of $total_matches pods have $target_count ready containers. Waiting ${check_interval}s..." + + sleep "$check_interval" + elapsed_time=$((elapsed_time + check_interval)) + done + + echo "Error: Timeout reached! After ${max_wait_seconds} seconds, not all pods reached $target_count ready containers." >&2 + return 1 +} + destroy_operator() { kubectl -n "${OPERATOR_NS:-$NAMESPACE}" delete deployment percona-postgresql-operator --force --grace-period=0 || true if [[ $OPERATOR_NS ]]; then diff --git a/e2e-tests/kuttl.yaml b/e2e-tests/kuttl.yaml index 9a06130c5f..f961b429aa 100644 --- a/e2e-tests/kuttl.yaml +++ b/e2e-tests/kuttl.yaml @@ -2,4 +2,4 @@ apiVersion: kuttl.dev/v1beta1 kind: TestSuite testDirs: - e2e-tests/tests -timeout: 180 +timeout: 600 diff --git a/e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml b/e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml index dde080db34..5d271cd318 100644 --- a/e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml +++ b/e2e-tests/tests/backup-enable-disable/03-disable-backups.yaml @@ -11,3 +11,5 @@ commands: | yq '.metadata.annotations."pgv2.percona.com/authorizeBackupRemoval"="true"' \ | yq '.spec.backups.enabled=false' \ | kubectl -n "${NAMESPACE}" apply -f - + + wait_for_ready_containers "some-name-instance1" 2 From 22754ceea120d76ae845a0755367446506bf9944 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Mon, 13 Oct 2025 14:40:42 +0300 Subject: [PATCH 175/300] bump k8s ver to 1.31 --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index fad0380576..a69081ebd7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -16,7 +16,7 @@ void createCluster(String CLUSTER_SUFFIX) { --preemptible \ --zone=${region} \ --machine-type='n1-standard-4' \ - --cluster-version='1.30' \ + --cluster-version='1.31' \ --num-nodes=3 \ --labels='delete-cluster-after-hours=6' \ --disk-size=30 \ From ef33f3be33f4954c86d30a17713e7e937d232676 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 01:02:10 +0000 Subject: [PATCH 176/300] CLOUD-727: Bump golang.org/x/tools from 0.37.0 to 0.38.0 Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.37.0 to 0.38.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.37.0...v0.38.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.38.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 7be5065fca..eaddcc6838 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.38.0 go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.42.0 + golang.org/x/crypto v0.43.0 google.golang.org/grpc v1.76.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.1 @@ -68,7 +68,7 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.28.0 // indirect + golang.org/x/mod v0.29.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect @@ -124,14 +124,14 @@ require ( go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.44.0 // indirect + golang.org/x/net v0.46.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.37.0 + golang.org/x/tools v0.38.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect diff --git a/go.sum b/go.sum index d121a52b61..223e7a4c8e 100644 --- a/go.sum +++ b/go.sum @@ -291,21 +291,21 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= -golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -322,18 +322,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= -golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -341,8 +341,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From dc610e2b5f93a510013c2652196814e77cda5204 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 14 Oct 2025 14:04:42 +0300 Subject: [PATCH 177/300] K8SPG-844 backup enabled checks --- percona/controller/pgcluster/backup.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 61835badec..37d19b3557 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -39,6 +39,10 @@ func (r *PGClusterReconciler) reconcileBackups(ctx context.Context, cr *v2.Perco func (r *PGClusterReconciler) cleanupOutdatedBackups(ctx context.Context, cr *v2.PerconaPGCluster) error { log := logging.FromContext(ctx) + if !cr.Spec.Backups.IsEnabled() { + return nil + } + if cr.Status.State != v2.AppStateReady { return nil } From c1f2c150d1bb24cbcb118d544638cc72d48e3f29 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Tue, 14 Oct 2025 14:25:32 +0300 Subject: [PATCH 178/300] K8SPG-647: remove major-upgrade from release tests --- e2e-tests/run-release.csv | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 29a2838467..8c480e198e 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -5,7 +5,6 @@ database-init-sql demand-backup finalizers init-deploy -major-upgrade monitoring monitoring-pmm3 one-pod From 051e015ed1f226bf2263eb6b8048bc0a867eb9ef Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Tue, 14 Oct 2025 16:56:17 +0300 Subject: [PATCH 179/300] commit logs when debug mode one handling --- e2e-tests/functions | 1 + percona/controller/pgbackup/controller.go | 1 - percona/watcher/wal.go | 5 ++++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 8c88ffc077..5a87226064 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -55,6 +55,7 @@ deploy_operator() { fi yq eval '.spec.template.spec.containers[0].image = "'${IMAGE}'"' "${DEPLOY_DIR}/${cw_prefix}operator.yaml" \ | yq eval '(.spec.template.spec.containers[] | select(.name=="operator") | .env[] | select(.name=="DISABLE_TELEMETRY") | .value) = "'${disable_telemetry}'"' - \ + | yq eval '(.spec.template.spec.containers[] | select(.name=="operator") | .env[] | select(.name=="LOG_LEVEL") | .value) = "DEBUG"' - \ | kubectl -n "${OPERATOR_NS:-$NAMESPACE}" apply -f - } diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index 3e5311ffe7..2ef563ac6e 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -297,7 +297,6 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re if err != nil { return reconcile.Result{}, errors.Wrap(err, "failed to create exec client") } - latestRestorableTime, err := watcher.GetLatestCommitTimestamp(ctx, r.Client, execCli, pgCluster, pgBackup) if err == nil { log.Info("Got latest restorable timestamp", "timestamp", latestRestorableTime) diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index c2aa12e6b8..179398bc5e 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -38,6 +38,10 @@ func GetWALWatcher(cr *pgv2.PerconaPGCluster) (string, WALWatcher) { func WatchCommitTimestamps(ctx context.Context, cli client.Client, eventChan chan event.GenericEvent, stopChan chan event.DeleteEvent, cr *pgv2.PerconaPGCluster) { log := logging.FromContext(ctx).WithName("WALWatcher") + if !cr.Spec.Backups.IsEnabled() { + return + } + log.Info("Watching commit timestamps") execCli, err := clientcmd.NewClient() @@ -69,7 +73,6 @@ func WatchCommitTimestamps(ctx context.Context, cli client.Client, eventChan cha continue } - ts, err := GetLatestCommitTimestamp(ctx, cli, execCli, localCr, latestBackup) if err != nil { switch { From b08eb9794d8efb3635810489f649605c054ffd37 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 15 Oct 2025 10:36:23 +0300 Subject: [PATCH 180/300] add an additional check for when the watch commit func is already in running state before the backups get disabled --- percona/watcher/wal.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index 179398bc5e..7bd1524091 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -65,6 +65,11 @@ func WatchCommitTimestamps(ctx context.Context, cli client.Client, eventChan cha return } + if !localCr.Spec.Backups.IsEnabled() { + log.Info("Backups are disabled, stopping WAL watcher") + return + } + latestBackup, err := getLatestBackup(ctx, cli, localCr) if err != nil { if !errors.Is(err, errRunningBackup) && !errors.Is(err, errNoBackups) { From 5749c0fd4665f3fc492fe54085334ba2fdd4eec1 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 16 Oct 2025 12:52:49 +0300 Subject: [PATCH 181/300] dont stop watcher, gate the logic and continue --- percona/controller/pgcluster/controller.go | 4 ++-- percona/watcher/wal.go | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 0400522404..b2dede1c63 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -978,6 +978,8 @@ func (r *PGClusterReconciler) reconcileExternalWatchers(ctx context.Context, cr } func (r *PGClusterReconciler) startExternalWatchers(ctx context.Context, cr *v2.PerconaPGCluster) error { + log := logging.FromContext(ctx) + if !cr.Spec.Backups.IsEnabled() { return nil } @@ -986,8 +988,6 @@ func (r *PGClusterReconciler) startExternalWatchers(ctx context.Context, cr *v2. return nil } - log := logging.FromContext(ctx) - watcherName, watcherFunc := watcher.GetWALWatcher(cr) if r.Watchers.IsExist(watcherName) { return nil diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index 7bd1524091..6fa0b93434 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -56,8 +56,6 @@ func WatchCommitTimestamps(ctx context.Context, cli client.Client, eventChan cha for { select { case <-ticker.C: - log.V(1).Info("Running WAL watcher") - localCr := cr.DeepCopy() err := cli.Get(ctx, client.ObjectKeyFromObject(cr), localCr) if err != nil { @@ -66,9 +64,9 @@ func WatchCommitTimestamps(ctx context.Context, cli client.Client, eventChan cha } if !localCr.Spec.Backups.IsEnabled() { - log.Info("Backups are disabled, stopping WAL watcher") - return + continue } + log.V(1).Info("Running WAL watcher") latestBackup, err := getLatestBackup(ctx, cli, localCr) if err != nil { From 541cb1f7df5928b1c29aa1389888068b5417d9b6 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 16 Oct 2025 16:40:30 +0300 Subject: [PATCH 182/300] K8SPG-879 patroni version check pod and container should align the resources for k8s version 1.34 --- percona/controller/pgcluster/controller.go | 27 +++++++++++-------- .../controller/pgcluster/controller_test.go | 20 ++++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 0400522404..9be9d13df3 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -456,6 +456,20 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, if len(cr.Spec.InstanceSets) == 0 { return errors.New(".spec.instances is a required value") // shouldn't happen as the value is required in the crd.yaml } + + // Using minimal resources since the patroni version check pod is performing a very simple + // operation i.e. "patronictl version" + resources := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + } + p = &corev1.Pod{ ObjectMeta: meta, Spec: corev1.PodSpec{ @@ -469,7 +483,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, Args: []string{ "-c", "sleep 60", }, - Resources: cr.Spec.InstanceSets[0].Resources, + Resources: resources, SecurityContext: initialize.RestrictedSecurityContext(cr.CompareVersion("2.8.0") >= 0), }, }, @@ -477,16 +491,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, Affinity: cr.Spec.InstanceSets[0].Affinity, TerminationGracePeriodSeconds: ptr.To(int64(5)), ImagePullSecrets: cr.Spec.ImagePullSecrets, - Resources: &corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("100m"), - corev1.ResourceMemory: resource.MustParse("64Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("50m"), - corev1.ResourceMemory: resource.MustParse("32Mi"), - }, - }, + Resources: &resources, }, } diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index a6d5574669..7c5d3926c5 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -2191,6 +2191,26 @@ var _ = Describe("patroni version check", Ordered, func() { Expect(pod.Spec.Containers[0].Image).To(Equal(cr2.Spec.Image)) Expect(pod.Spec.Containers[0].Command).To(Equal([]string{"bash"})) Expect(pod.Spec.Containers[0].Args).To(Equal([]string{"-c", "sleep 60"})) + Expect(pod.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + })) + Expect(pod.Spec.Resources).To(Equal(&corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + })) uid := int64(1001) expectedSecurityContext := &corev1.PodSecurityContext{ From 5dd563869118efa9793cb3c114607a32817e05fa Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 16 Oct 2025 16:56:07 +0300 Subject: [PATCH 183/300] enable feature gates for pod level resources --- percona/controller/pgcluster/suite_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/percona/controller/pgcluster/suite_test.go b/percona/controller/pgcluster/suite_test.go index 19d7ad4ed8..b5bc33f1d6 100644 --- a/percona/controller/pgcluster/suite_test.go +++ b/percona/controller/pgcluster/suite_test.go @@ -44,8 +44,13 @@ var _ = BeforeSuite(func() { testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: true, + ControlPlane: envtest.ControlPlane{ + APIServer: &envtest.APIServer{}, + }, } + testEnv.ControlPlane.APIServer.Configure().Set("feature-gates", "PodLevelResources=true") + var err error cfg, err = testEnv.Start() Expect(err).NotTo(HaveOccurred()) From da16d8307287db02d6e5b78c30dd00c00f99c37d Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 16 Oct 2025 16:56:54 +0300 Subject: [PATCH 184/300] add comment for justification --- percona/controller/pgcluster/suite_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/percona/controller/pgcluster/suite_test.go b/percona/controller/pgcluster/suite_test.go index b5bc33f1d6..3adb928c85 100644 --- a/percona/controller/pgcluster/suite_test.go +++ b/percona/controller/pgcluster/suite_test.go @@ -49,6 +49,7 @@ var _ = BeforeSuite(func() { }, } + // PodLevelResources feature gate is enabled by default on k8s 1.34. testEnv.ControlPlane.APIServer.Configure().Set("feature-gates", "PodLevelResources=true") var err error From 5a83d0162aadee7466e7fa9cb4ac8875ac51df32 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 17 Oct 2025 13:13:49 +0300 Subject: [PATCH 185/300] K8SPG-869 minimum repos should be required only when backups are enabled --- .../generated/pgv2.percona.com_perconapgclusters.yaml | 6 +++++- config/crd/bases/pgv2.percona.com_perconapgclusters.yaml | 6 +++++- deploy/bundle.yaml | 6 +++++- deploy/crd.yaml | 6 +++++- deploy/cw-bundle.yaml | 6 +++++- pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go | 3 ++- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index b31dda3640..b891c8597b 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -5870,7 +5870,6 @@ spec: required: - name type: object - minItems: 1 type: array x-kubernetes-list-map-keys: - name @@ -7091,6 +7090,11 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + x-kubernetes-validations: + - message: At least one repository must be configured when backups + are enabled + rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) + > 0' crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 8b38ce51f4..4aa8ead8d4 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -6275,7 +6275,6 @@ spec: required: - name type: object - minItems: 1 type: array x-kubernetes-list-map-keys: - name @@ -7496,6 +7495,11 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + x-kubernetes-validations: + - message: At least one repository must be configured when backups + are enabled + rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) + > 0' crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 97b02f85f9..2acb7e8208 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -6572,7 +6572,6 @@ spec: required: - name type: object - minItems: 1 type: array x-kubernetes-list-map-keys: - name @@ -7793,6 +7792,11 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + x-kubernetes-validations: + - message: At least one repository must be configured when backups + are enabled + rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) + > 0' crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 9124e34575..ce30ba6ba0 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -6572,7 +6572,6 @@ spec: required: - name type: object - minItems: 1 type: array x-kubernetes-list-map-keys: - name @@ -7793,6 +7792,11 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + x-kubernetes-validations: + - message: At least one repository must be configured when backups + are enabled + rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) + > 0' crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 8d766bd59c..2497d3efa1 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -6572,7 +6572,6 @@ spec: required: - name type: object - minItems: 1 type: array x-kubernetes-list-map-keys: - name @@ -7793,6 +7792,11 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + x-kubernetes-validations: + - message: At least one repository must be configured when backups + are enabled + rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) + > 0' crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 8b0fb316ec..87787253f8 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -476,6 +476,8 @@ type Patroni struct { Version string `json:"version"` } +// Backups struct. +// +kubebuilder:validation:XValidation:rule="!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) > 0",message="At least one repository must be configured when backups are enabled" type Backups struct { Enabled *bool `json:"enabled,omitempty"` @@ -562,7 +564,6 @@ type PGBackRestArchive struct { Jobs *crunchyv1beta1.BackupJobs `json:"jobs,omitempty"` // Defines a pgBackRest repository - // +kubebuilder:validation:MinItems=1 // +listType=map // +listMapKey=name Repos []crunchyv1beta1.PGBackRestRepo `json:"repos"` From 269486263c519a721d57e486e36bc71e833cd7af Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 17 Oct 2025 14:00:19 +0300 Subject: [PATCH 186/300] fixes on the validation rule + unit tests --- .../pgv2.percona.com_perconapgclusters.yaml | 4 +- .../pgv2.percona.com_perconapgclusters.yaml | 4 +- deploy/bundle.yaml | 4 +- deploy/crd.yaml | 4 +- deploy/cw-bundle.yaml | 4 +- .../controller/pgcluster/controller_test.go | 68 +++++++++++++++++++ .../v2/perconapgcluster_types.go | 2 +- 7 files changed, 79 insertions(+), 11 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index b891c8597b..c6207c5144 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -7093,8 +7093,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) - > 0' + rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) + > 0 crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 4aa8ead8d4..1dc1ef2464 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -7498,8 +7498,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) - > 0' + rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) + > 0 crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 2acb7e8208..2f326a7c7b 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -7795,8 +7795,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) - > 0' + rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) + > 0 crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/crd.yaml b/deploy/crd.yaml index ce30ba6ba0..2e75d79bbc 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -7795,8 +7795,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) - > 0' + rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) + > 0 crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 2497d3efa1..19bf06c047 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -7795,8 +7795,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: '!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) - > 0' + rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) + > 0 crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index a6d5574669..dd05f9a473 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -2333,6 +2333,74 @@ var _ = Describe("CR Validations", Ordered, func() { }) }) }) + + Context("Backup repository validations", Ordered, func() { + When("creating a CR with valid backup configurations", func() { + It("should accept backups disabled with no repositories", func() { + cr, err := readDefaultCR("cr-validation-backup-1", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.Backups.Enabled = &f + cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{} + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + + It("should accept backups enabled with at least one repository", func() { + cr, err := readDefaultCR("cr-validation-backup-2", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.Backups.Enabled = &t + cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{ + {Name: "repo1"}, + } + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + + It("should accept backups enabled (nil - default true) with repositories", func() { + cr, err := readDefaultCR("cr-validation-backup-3", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.Backups.Enabled = nil // defaults to enabled + cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{ + {Name: "repo1"}, + } + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + }) + + When("creating a CR with invalid backup configurations", func() { + It("should reject backups enabled with no repositories", func() { + cr, err := readDefaultCR("cr-validation-backup-4", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.Backups.Enabled = &t + cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{} + + err = k8sClient.Create(ctx, cr) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring( + "At least one repository must be configured when backups are enabled", + )) + }) + + It("should reject backups enabled (nil - default true) with no repositories", func() { + cr, err := readDefaultCR("cr-validation-backup-5", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.Backups.Enabled = nil // defaults to enabled + cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{} + + err = k8sClient.Create(ctx, cr) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring( + "At least one repository must be configured when backups are enabled", + )) + }) + }) + }) }) var _ = Describe("Init Container", Ordered, func() { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 87787253f8..ffa75d94e9 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -477,7 +477,7 @@ type Patroni struct { } // Backups struct. -// +kubebuilder:validation:XValidation:rule="!has(self.enabled) || self.enabled == false || size(self.pgbackrest.repos) > 0",message="At least one repository must be configured when backups are enabled" +// +kubebuilder:validation:XValidation:rule="(has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) > 0",message="At least one repository must be configured when backups are enabled" type Backups struct { Enabled *bool `json:"enabled,omitempty"` From 51a6d6dc5bcf2783dd7b1bc31ee38e54d014ea93 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Fri, 17 Oct 2025 14:41:18 +0300 Subject: [PATCH 187/300] cr: add test case for backups disabled with at least one repo available --- .../controller/pgcluster/controller_test.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index e83d0bf220..548ef3a0c0 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -2378,10 +2378,22 @@ var _ = Describe("CR Validations", Ordered, func() { Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) }) - It("should accept backups enabled (nil - default true) with repositories", func() { + It("should accept backups disabled with at least one repository", func() { cr, err := readDefaultCR("cr-validation-backup-3", ns) Expect(err).NotTo(HaveOccurred()) + cr.Spec.Backups.Enabled = &f + cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{ + {Name: "repo1"}, + } + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) + + It("should accept backups enabled (nil - default true) with repositories", func() { + cr, err := readDefaultCR("cr-validation-backup-4", ns) + Expect(err).NotTo(HaveOccurred()) + cr.Spec.Backups.Enabled = nil // defaults to enabled cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{ {Name: "repo1"}, @@ -2393,7 +2405,7 @@ var _ = Describe("CR Validations", Ordered, func() { When("creating a CR with invalid backup configurations", func() { It("should reject backups enabled with no repositories", func() { - cr, err := readDefaultCR("cr-validation-backup-4", ns) + cr, err := readDefaultCR("cr-validation-backup-5", ns) Expect(err).NotTo(HaveOccurred()) cr.Spec.Backups.Enabled = &t @@ -2407,7 +2419,7 @@ var _ = Describe("CR Validations", Ordered, func() { }) It("should reject backups enabled (nil - default true) with no repositories", func() { - cr, err := readDefaultCR("cr-validation-backup-5", ns) + cr, err := readDefaultCR("cr-validation-backup-6", ns) Expect(err).NotTo(HaveOccurred()) cr.Spec.Backups.Enabled = nil // defaults to enabled From 94fc9d6cc35f006aa7ac37017806a4c4f968b477 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 20 Oct 2025 14:07:56 +0300 Subject: [PATCH 188/300] K8SPG-869 make repo field completely optional --- .../pgv2.percona.com_perconapgclusters.yaml | 6 ++---- .../bases/pgv2.percona.com_perconapgclusters.yaml | 6 ++---- deploy/bundle.yaml | 6 ++---- deploy/crd.yaml | 6 ++---- deploy/cw-bundle.yaml | 6 ++---- percona/controller/pgcluster/controller_test.go | 14 ++++++++++++-- .../pgv2.percona.com/v2/perconapgcluster_types.go | 3 ++- 7 files changed, 24 insertions(+), 23 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index c6207c5144..146702e4e3 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -7083,8 +7083,6 @@ spec: type: object type: object type: object - required: - - repos type: object trackLatestRestorableTime: description: Enable tracking latest restorable time @@ -7093,8 +7091,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) - > 0 + rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) + && size(self.pgbackrest.repos) > 0) crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 1dc1ef2464..7f460f98e6 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -7488,8 +7488,6 @@ spec: type: object type: object type: object - required: - - repos type: object trackLatestRestorableTime: description: Enable tracking latest restorable time @@ -7498,8 +7496,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) - > 0 + rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) + && size(self.pgbackrest.repos) > 0) crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 2f326a7c7b..31d068ee55 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -7785,8 +7785,6 @@ spec: type: object type: object type: object - required: - - repos type: object trackLatestRestorableTime: description: Enable tracking latest restorable time @@ -7795,8 +7793,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) - > 0 + rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) + && size(self.pgbackrest.repos) > 0) crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 2e75d79bbc..b60abde036 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -7785,8 +7785,6 @@ spec: type: object type: object type: object - required: - - repos type: object trackLatestRestorableTime: description: Enable tracking latest restorable time @@ -7795,8 +7793,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) - > 0 + rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) + && size(self.pgbackrest.repos) > 0) crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 19bf06c047..55dc50b8cc 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -7785,8 +7785,6 @@ spec: type: object type: object type: object - required: - - repos type: object trackLatestRestorableTime: description: Enable tracking latest restorable time @@ -7795,8 +7793,8 @@ spec: x-kubernetes-validations: - message: At least one repository must be configured when backups are enabled - rule: (has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) - > 0 + rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) + && size(self.pgbackrest.repos) > 0) crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 548ef3a0c0..1e9768fae3 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -2401,11 +2401,21 @@ var _ = Describe("CR Validations", Ordered, func() { Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) }) + + It("should accept backups disabled with repositories not existing (nil)", func() { + cr, err := readDefaultCR("cr-validation-backup-5", ns) + Expect(err).NotTo(HaveOccurred()) + + cr.Spec.Backups.Enabled = &f + cr.Spec.Backups.PGBackRest.Repos = nil + + Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) + }) }) When("creating a CR with invalid backup configurations", func() { It("should reject backups enabled with no repositories", func() { - cr, err := readDefaultCR("cr-validation-backup-5", ns) + cr, err := readDefaultCR("cr-validation-backup-1", ns) Expect(err).NotTo(HaveOccurred()) cr.Spec.Backups.Enabled = &t @@ -2419,7 +2429,7 @@ var _ = Describe("CR Validations", Ordered, func() { }) It("should reject backups enabled (nil - default true) with no repositories", func() { - cr, err := readDefaultCR("cr-validation-backup-6", ns) + cr, err := readDefaultCR("cr-validation-backup-2", ns) Expect(err).NotTo(HaveOccurred()) cr.Spec.Backups.Enabled = nil // defaults to enabled diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index ffa75d94e9..df12c0790e 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -477,7 +477,7 @@ type Patroni struct { } // Backups struct. -// +kubebuilder:validation:XValidation:rule="(has(self.enabled) && self.enabled == false) || size(self.pgbackrest.repos) > 0",message="At least one repository must be configured when backups are enabled" +// +kubebuilder:validation:XValidation:rule="(has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) && size(self.pgbackrest.repos) > 0)",message="At least one repository must be configured when backups are enabled" type Backups struct { Enabled *bool `json:"enabled,omitempty"` @@ -566,6 +566,7 @@ type PGBackRestArchive struct { // Defines a pgBackRest repository // +listType=map // +listMapKey=name + // +optional Repos []crunchyv1beta1.PGBackRestRepo `json:"repos"` // Defines configuration for a pgBackRest dedicated repository host. This section is only From 2d8ba854e2edfae2ee8a312599ae52cc7624e0ad Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 20 Oct 2025 14:36:09 +0300 Subject: [PATCH 189/300] add unit test for enabled backups with nil repos - throw error --- percona/controller/pgcluster/controller_test.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 1e9768fae3..cda9cd1ab2 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -2428,10 +2428,24 @@ var _ = Describe("CR Validations", Ordered, func() { )) }) - It("should reject backups enabled (nil - default true) with no repositories", func() { + It("should reject backups enabled with no repositories (nil)", func() { cr, err := readDefaultCR("cr-validation-backup-2", ns) Expect(err).NotTo(HaveOccurred()) + cr.Spec.Backups.Enabled = &t + cr.Spec.Backups.PGBackRest.Repos = nil + + err = k8sClient.Create(ctx, cr) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring( + "At least one repository must be configured when backups are enabled", + )) + }) + + It("should reject backups enabled (nil - default true) with no repositories", func() { + cr, err := readDefaultCR("cr-validation-backup-3", ns) + Expect(err).NotTo(HaveOccurred()) + cr.Spec.Backups.Enabled = nil // defaults to enabled cr.Spec.Backups.PGBackRest.Repos = []v1beta1.PGBackRestRepo{} From d8248fe15e5715163e8b5eea8f4d3d7db371447f Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Thu, 23 Oct 2025 11:51:09 +0300 Subject: [PATCH 190/300] K8SPG-883 support cr.Status.PatroniVersion and cr.Status.Patroni.Version (#1331) --- .../pgv2.percona.com_perconapgclusters.yaml | 4 + .../pgv2.percona.com_perconapgclusters.yaml | 4 + deploy/bundle.yaml | 4 + deploy/crd.yaml | 4 + deploy/cw-bundle.yaml | 4 + percona/controller/pgcluster/controller.go | 105 ++++++++++++------ .../controller/pgcluster/controller_test.go | 6 + percona/postgres/common.go | 8 +- percona/watcher/wal_test.go | 4 + .../v2/perconapgcluster_types.go | 5 + 10 files changed, 115 insertions(+), 33 deletions(-) diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 146702e4e3..893d1911a0 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -21143,6 +21143,10 @@ spec: version: type: string type: object + patroniVersion: + description: 'Deprecated: Use Patroni instead. This field will be + removed in a future release.' + type: string pgbackrest: description: Status information for pgBackRest properties: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 7f460f98e6..7fb6e89327 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -21548,6 +21548,10 @@ spec: version: type: string type: object + patroniVersion: + description: 'Deprecated: Use Patroni instead. This field will be + removed in a future release.' + type: string pgbackrest: description: Status information for pgBackRest properties: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 31d068ee55..e93e6e85ad 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -21845,6 +21845,10 @@ spec: version: type: string type: object + patroniVersion: + description: 'Deprecated: Use Patroni instead. This field will be + removed in a future release.' + type: string pgbackrest: description: Status information for pgBackRest properties: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index b60abde036..be4cee1441 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -21845,6 +21845,10 @@ spec: version: type: string type: object + patroniVersion: + description: 'Deprecated: Use Patroni instead. This field will be + removed in a future release.' + type: string pgbackrest: description: Status information for pgBackRest properties: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 55dc50b8cc..669b9940ec 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -21845,6 +21845,10 @@ spec: version: type: string type: object + patroniVersion: + description: 'Deprecated: Use Patroni instead. This field will be + removed in a future release.' + type: string pgbackrest: description: Status information for pgBackRest properties: diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index cf59fc4f10..87720b05f5 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -374,8 +374,6 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, } if patroniVersion, ok := cr.Annotations[pNaming.AnnotationCustomPatroniVersion]; ok { - cr.Annotations[pNaming.AnnotationPatroniVersion] = patroniVersion - patroniVersionUpdateFunc := func() error { cluster := &v2.PerconaPGCluster{} if err := r.Client.Get(ctx, types.NamespacedName{ @@ -388,10 +386,17 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, orig := cluster.DeepCopy() cluster.Status.Patroni.Version = patroniVersion + cluster.Status.PatroniVersion = patroniVersion if err := r.Client.Status().Patch(ctx, cluster.DeepCopy(), client.MergeFrom(orig)); err != nil { return errors.Wrap(err, "failed to patch patroni version") } + + err := r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + return nil } @@ -403,40 +408,29 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, return nil } - getImageIDFromPod := func(pod *corev1.Pod, containerName string) string { - idx := slices.IndexFunc(pod.Status.ContainerStatuses, func(s corev1.ContainerStatus) bool { - return s.Name == containerName - }) - if idx == -1 { - return "" - } - return pod.Status.ContainerStatuses[idx].ImageID - } - - pods := new(corev1.PodList) - instances, err := naming.AsSelector(naming.ClusterInstances(cr.Name)) + imageIDs, err := r.instanceImageIDs(ctx, cr) if err != nil { - return err - } - if err = r.Client.List(ctx, pods, client.InNamespace(cr.Namespace), client.MatchingLabelsSelector{Selector: instances}); err != nil { - return err - } - - // Collecting all image IDs from instance pods. Under normal conditions, this slice will contain a single image ID, as all pods typically use the same image. - // During an image update, it may contain multiple different image IDs as the update progresses. - imageIDs := []string{} - for _, pod := range pods.Items { - imageID := getImageIDFromPod(&pod, naming.ContainerDatabase) - if imageID != "" && !slices.Contains(imageIDs, imageID) { - imageIDs = append(imageIDs, imageID) - } + return errors.Wrap(err, "get image IDs") } // If the imageIDs slice contains the imageID from the status, we skip checking the Patroni version. // This ensures that the Patroni version is only checked after all pods have been updated. - if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.Patroni.Version != "" { - cr.Annotations[pNaming.AnnotationPatroniVersion] = cr.Status.Patroni.Version - return nil + if cr.CompareVersion("2.8.0") >= 0 { + if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.Patroni.Version != "" { + err = r.patchPatroniVersionAnnotation(ctx, cr, cr.Status.Patroni.Version) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + return nil + } + } else { + if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.PatroniVersion != "" { + err = r.patchPatroniVersionAnnotation(ctx, cr, cr.Status.PatroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + return nil + } } meta := metav1.ObjectMeta{ @@ -535,6 +529,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, orig := cr.DeepCopy() cr.Status.Patroni.Version = patroniVersion + cr.Status.PatroniVersion = patroniVersion cr.Status.Postgres.Version = cr.Spec.PostgresVersion cr.Status.Postgres.ImageID = getImageIDFromPod(p, pNaming.ContainerPatroniVersionCheck) @@ -542,14 +537,60 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, return errors.Wrap(err, "failed to patch patroni version") } + err = r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + if err := r.Client.Delete(ctx, p); err != nil { return errors.Wrap(err, "failed to delete patroni version check pod") } - cr.Annotations[pNaming.AnnotationPatroniVersion] = patroniVersion return nil } +func (r *PGClusterReconciler) patchPatroniVersionAnnotation(ctx context.Context, cr *v2.PerconaPGCluster, patroniVersion string) error { + orig := cr.DeepCopy() + cr.Annotations[pNaming.AnnotationPatroniVersion] = patroniVersion + if err := r.Client.Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "failed to patch the pg cluster") + } + return nil +} + +func (r *PGClusterReconciler) instanceImageIDs(ctx context.Context, cr *v2.PerconaPGCluster) ([]string, error) { + pods := new(corev1.PodList) + instances, err := naming.AsSelector(naming.ClusterInstances(cr.Name)) + if err != nil { + return nil, errors.Wrap(err, "failed to create a selector for instance pods") + } + if err = r.Client.List(ctx, pods, client.InNamespace(cr.Namespace), client.MatchingLabelsSelector{Selector: instances}); err != nil { + return nil, errors.Wrap(err, "failed to list instances") + } + + // Collecting all image IDs from instance pods. Under normal conditions, this slice will contain a single image ID, as all pods typically use the same image. + // During an image update, it may contain multiple different image IDs as the update progresses. + var imageIDs []string + for _, pod := range pods.Items { + imageID := getImageIDFromPod(&pod, naming.ContainerDatabase) + if imageID != "" && !slices.Contains(imageIDs, imageID) { + imageIDs = append(imageIDs, imageID) + } + } + + return imageIDs, nil +} + +func getImageIDFromPod(pod *corev1.Pod, containerName string) string { + idx := slices.IndexFunc(pod.Status.ContainerStatuses, func(s corev1.ContainerStatus) bool { + return s.Name == containerName + }) + if idx == -1 { + return "" + } + return pod.Status.ContainerStatuses[idx].ImageID +} + func (r *PGClusterReconciler) reconcileTLS(ctx context.Context, cr *v2.PerconaPGCluster) error { if err := r.validateTLS(ctx, cr); err != nil { return errors.Wrap(err, "validate TLS") diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index cda9cd1ab2..5e39b24579 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -2079,6 +2079,8 @@ var _ = Describe("patroni version check", Ordered, func() { Expect(k8sClient.Get(ctx, crNamespacedName, updatedCR)).Should(Succeed()) Expect(updatedCR.Status.Patroni.Version).To(Equal("3.2.1")) + Expect(updatedCR.Status.PatroniVersion).To(Equal("3.2.1")) + Expect(updatedCR.Annotations[pNaming.AnnotationPatroniVersion]).To(Equal("3.2.1")) }) }) @@ -2134,7 +2136,9 @@ var _ = Describe("patroni version check", Ordered, func() { } cr2.Status.Patroni.Version = "3.1.0" + cr2.Status.PatroniVersion = "3.1.0" cr2.Status.Postgres.ImageID = "some-image-id" + cr2.Annotations[pNaming.AnnotationPatroniVersion] = "3.1.0" status := cr2.Status Expect(k8sClient.Create(ctx, cr2)).Should(Succeed()) @@ -2240,6 +2244,8 @@ var _ = Describe("patroni version check", Ordered, func() { Expect(k8sClient.Get(ctx, crNamespacedName2, updatedCR)).Should(Succeed()) Expect(updatedCR.Status.Patroni.Version).To(Equal("3.1.0")) + Expect(updatedCR.Status.PatroniVersion).To(Equal("3.1.0")) + Expect(updatedCR.Annotations[pNaming.AnnotationPatroniVersion]).To(Equal("3.1.0")) }) }) }) diff --git a/percona/postgres/common.go b/percona/postgres/common.go index 2f9ba62cfc..f0a8c05b5a 100644 --- a/percona/postgres/common.go +++ b/percona/postgres/common.go @@ -17,7 +17,13 @@ func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGClust // K8SPG-648: patroni v4.0.0 deprecated "master" role. // We should use "primary" instead role := "primary" - patroniVer, err := gover.NewVersion(cr.Status.Patroni.Version) + + patroniVersion := cr.Status.PatroniVersion + if cr.CompareVersion("2.8.0") >= 0 { + patroniVersion = cr.Status.Patroni.Version + } + + patroniVer, err := gover.NewVersion(patroniVersion) if err != nil { return nil, errors.Wrap(err, "failed to get patroni version") } diff --git a/percona/watcher/wal_test.go b/percona/watcher/wal_test.go index 757bc329f8..d50375a8ee 100644 --- a/percona/watcher/wal_test.go +++ b/percona/watcher/wal_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/percona/percona-postgresql-operator/v2/percona/version" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -343,6 +344,9 @@ func TestGetLatestCommitTimestamp(t *testing.T) { Version: "error", }, }, + Spec: pgv2.PerconaPGClusterSpec{ + CRVersion: version.Version(), + }, }, expectedErr: errors.New("failed to get patroni version: Malformed version: error: primary pod not found"), }, diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index df12c0790e..c950927e7d 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -442,6 +442,11 @@ type PerconaPGClusterStatus struct { // +operator-sdk:csv:customresourcedefinitions:type=status State AppState `json:"state"` + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status + // Deprecated: Use Patroni instead. This field will be removed in a future release. + PatroniVersion string `json:"patroniVersion"` + // +optional // +operator-sdk:csv:customresourcedefinitions:type=status Patroni Patroni `json:"patroni,omitempty"` From 2f57481ffc3a4631a7d343a75c1693de7d3158dd Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Thu, 23 Oct 2025 16:53:48 +0300 Subject: [PATCH 191/300] K8SPG-836: Add separate check for ppg13&14 grantPublicSchemaAccess (#1332) * Do not test grantPublicSchemaAccess for PPG < 15 * Improve skipping code * Add check for the error instead of skipping * Assign PG_VER based on POSTGRES image if not set * Update e2e-tests/vars.sh Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * update vars --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- ...custom-user-with-public-schema-access.yaml | 16 ++++++++--- .../users/14-write-data-to-custom-db.yaml | 27 ++++++++++--------- .../users/15-read-from-primary-custom-db.yaml | 20 ++++++++------ e2e-tests/vars.sh | 13 ++++++--- 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml b/e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml index 99c81c5d0d..7ad867dfc0 100644 --- a/e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml +++ b/e2e-tests/tests/users/13-add-custom-user-with-public-schema-access.yaml @@ -7,6 +7,16 @@ commands: set -o xtrace source ../../functions - - kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=json -p '[{"op":"add", "path":"/spec/autoCreateUserSchema","value":true},{"op":"add", "path":"/spec/users","value":[{"name":"chico","databases":["spain"],"password":{"type":"ASCII"},"secretName":"chico-credentials", "grantPublicSchemaAccess": true}]}]' - sleep 10 + if [[ $PG_VER < 15 ]]; then + # grantPublicSchemaAccess is not supported before PPG15. Checking that applying patch fails." + set +o errexit + patch_output=$(kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=json -p '[{"op":"add", "path":"/spec/autoCreateUserSchema","value":true},{"op":"add", "path":"/spec/users","value":[{"name":"chico","databases":["spain"],"password":{"type":"ASCII"},"secretName":"chico-credentials", "grantPublicSchemaAccess": true}]}]' 2>&1) + set -o errexit + if [[ $patch_output != 'The PerconaPGCluster "users" is invalid: spec: Invalid value: "object": PostgresVersion must be >= 15 if grantPublicSchemaAccess exists and is true' ]]; then + echo "grantPublicSchemaAccess is not supported before PPG15. Current PG_VER = $PG_VER but the patch was applied" + exit 1 + fi + else + kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=json -p '[{"op":"add", "path":"/spec/autoCreateUserSchema","value":true},{"op":"add", "path":"/spec/users","value":[{"name":"chico","databases":["spain"],"password":{"type":"ASCII"},"secretName":"chico-credentials", "grantPublicSchemaAccess": true}]}]' + sleep 10 + fi diff --git a/e2e-tests/tests/users/14-write-data-to-custom-db.yaml b/e2e-tests/tests/users/14-write-data-to-custom-db.yaml index e395acbb7b..dd07f6912c 100644 --- a/e2e-tests/tests/users/14-write-data-to-custom-db.yaml +++ b/e2e-tests/tests/users/14-write-data-to-custom-db.yaml @@ -7,16 +7,19 @@ commands: source ../../functions - password=$(get_psql_user_pass chico-credentials) - user='chico' - db_name='spain' - schema='public' - hostname=$(get_pgbouncer_host chico-credentials) + if [[ $PG_VER < 15 ]]; then + echo "grantPublicSchemaAccess is not supported before PPG15. Current PG_VER = $PG_VER. Skipping check" + else + password=$(get_psql_user_pass chico-credentials) + user='chico' + db_name='spain' + schema='public' + hostname=$(get_pgbouncer_host chico-credentials) - run_psql \ - 'SET search_path TO public;CREATE TABLE IF NOT EXISTS customApp (id int PRIMARY KEY);' \ - "-h $hostname -U $user -d $db_name" "$password" - run_psql \ - "INSERT INTO $schema.customApp (id) VALUES (100500)" \ - "-h $hostname -U $user -d $db_name" "$password" - + run_psql \ + 'SET search_path TO public;CREATE TABLE IF NOT EXISTS customApp (id int PRIMARY KEY);' \ + "-h $hostname -U $user -d $db_name" "$password" + run_psql \ + "INSERT INTO $schema.customApp (id) VALUES (100500)" \ + "-h $hostname -U $user -d $db_name" "$password" + fi diff --git a/e2e-tests/tests/users/15-read-from-primary-custom-db.yaml b/e2e-tests/tests/users/15-read-from-primary-custom-db.yaml index 04d6b2c43b..c30648c174 100644 --- a/e2e-tests/tests/users/15-read-from-primary-custom-db.yaml +++ b/e2e-tests/tests/users/15-read-from-primary-custom-db.yaml @@ -7,13 +7,17 @@ commands: set -o xtrace source ../../functions + if [[ $PG_VER < 15 ]]; then + echo "grantPublicSchemaAccess is not supported before PPG15. Current PG_VER = $PG_VER. Creating dummy configmap to pass check" + kubectl create configmap -n "${NAMESPACE}" 10-read-from-primary-custom-db --from-literal=data=' 100500' + else + password=$(get_psql_user_pass chico-credentials) + user='chico' + db_name='spain' + schema='public' + hostname=$(get_pgbouncer_host chico-credentials) - password=$(get_psql_user_pass chico-credentials) - user='chico' - db_name='spain' - schema='public' - hostname=$(get_pgbouncer_host chico-credentials) + data=$(run_psql "SELECT * from $schema.customApp;" "-h $hostname -U $user -d $db_name" "$password") - data=$(run_psql "SELECT * from $schema.customApp;" "-h $hostname -U $user -d $db_name" "$password") - - kubectl create configmap -n "${NAMESPACE}" 10-read-from-primary-custom-db --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 10-read-from-primary-custom-db --from-literal=data="${data}" + fi diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index e7274d7f81..42691936e0 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -23,7 +23,12 @@ fi export IMAGE_BASE=${IMAGE_BASE:-"perconalab/percona-postgresql-operator"} export IMAGE=${IMAGE:-"${IMAGE_BASE}:${VERSION}"} -export PG_VER="${PG_VER:-17}" +if [[ ! $PG_VER && $IMAGE_POSTGRESQL ]]; then + pg_version_value=$(echo "$IMAGE_POSTGRESQL" | sed -E 's/.*:(.*ppg)?([0-9]+).*/\2/') + export PG_VER="${pg_version_value}" +else + export PG_VER="${PG_VER:-17}" +fi export IMAGE_PGBOUNCER=${IMAGE_PGBOUNCER:-"${IMAGE_BASE}:main-pgbouncer$PG_VER"} export IMAGE_POSTGRESQL=${IMAGE_POSTGRESQL:-"perconalab/percona-distribution-postgresql:$PG_VER"} export IMAGE_BACKREST=${IMAGE_BACKREST:-"${IMAGE_BASE}:main-pgbackrest$PG_VER"} @@ -49,10 +54,10 @@ for var in $(printenv | grep -E '^IMAGE' | awk -F'=' '{print $1}'); do fi if [[ $var_value == percona/* || $var_value == perconalab/* ]]; then new_value="${REGISTRY_NAME_FULL}${var_value}" - export "$var=$new_value" - echo $var=$new_value + export "$var"="$new_value" + echo "$var"="$new_value" fi - echo $IMAGE + echo "$IMAGE" done # shellcheck disable=SC2034 From f96c9d5a1859dfcfbe9803f166cb57a9837f6f61 Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Mon, 27 Oct 2025 19:01:31 -0300 Subject: [PATCH 192/300] Add table for test duration in GH report --- Jenkinsfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index a69081ebd7..ae8fb6136c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -205,7 +205,10 @@ void makeReport() { TestsReport = TestsReport + "\r\n| " + testName + " | [" + testResult + "](" + testUrl + ") | " + formatTime(testTime) + " |" TestsReportXML = TestsReportXML + '<'+ testResult +'/>\n' } - TestsReport = TestsReport + "\r\n| We run $startedTestAmount out of $wholeTestAmount | | " + formatTime(totalTestTime) + " |" + TestsReport = TestsReport + "\r\n\r\n| Summary | Value |\r\n| ------- | ----- |" + TestsReport = TestsReport + "\r\n| Tests Run | $startedTestAmount/$wholeTestAmount |" + TestsReport = TestsReport + "\r\n| Job Duration | " + formatTime(currentBuild.duration / 1000) + " |" + TestsReport = TestsReport + "\r\n| Total Test Time | " + formatTime(totalTestTime) + " |" TestsReportXML = TestsReportXML + '\n' sh """ From fb402ea923db2d6eaea816ccbbb85703c5096353 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:06:40 +0200 Subject: [PATCH 193/300] CLOUD-727: Bump github.com/kubernetes-csi/external-snapshotter/client/v8 (#1338) Bumps [github.com/kubernetes-csi/external-snapshotter/client/v8](https://github.com/kubernetes-csi/external-snapshotter) from 8.2.0 to 8.4.0. - [Release notes](https://github.com/kubernetes-csi/external-snapshotter/releases) - [Commits](https://github.com/kubernetes-csi/external-snapshotter/compare/v8.2.0...v8.4.0) --- updated-dependencies: - dependency-name: github.com/kubernetes-csi/external-snapshotter/client/v8 dependency-version: 8.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eaddcc6838..e8ed6f769a 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.7.0 - github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 + github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 github.com/onsi/ginkgo/v2 v2.26.0 github.com/onsi/gomega v1.38.2 github.com/pganalyze/pg_query_go/v6 v6.1.0 diff --git a/go.sum b/go.sum index 223e7a4c8e..edddbb754b 100644 --- a/go.sum +++ b/go.sum @@ -149,8 +149,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0 h1:Q3jQ1NkFqv5o+F8dMmHd8SfEmlcwNeo1immFApntEwE= -github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y= +github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 h1:bMqrb3UHgHbP+PW9VwiejfDJU1R0PpXVZNMdeH8WYKI= +github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= From da934eb71acb618b89bd1f64ef5baf28a3657da2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:09:56 +0200 Subject: [PATCH 194/300] CLOUD-727: Bump github.com/onsi/ginkgo/v2 from 2.26.0 to 2.27.2 (#1337) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.26.0 to 2.27.2. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.26.0...v2.27.2) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-version: 2.27.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 3 +-- go.sum | 12 ++++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index e8ed6f769a..359ce160e3 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.7.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 - github.com/onsi/ginkgo/v2 v2.26.0 + github.com/onsi/ginkgo/v2 v2.27.2 github.com/onsi/gomega v1.38.2 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 @@ -65,7 +65,6 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/mod v0.29.0 // indirect diff --git a/go.sum b/go.sum index edddbb754b..a230753b7d 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BN github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= -github.com/gkampitakis/go-snaps v0.5.14 h1:3fAqdB6BCPKHDMHAKRwtPUwYexKtGrNuw8HX/T/4neo= -github.com/gkampitakis/go-snaps v0.5.14/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= +github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= +github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -179,8 +179,8 @@ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= -github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= -github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= @@ -190,8 +190,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= @@ -275,8 +273,6 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= From 5a83485f0b8ca48b82350a799b9bd9a690015678 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:18:32 +0200 Subject: [PATCH 195/300] CLOUD-727: Bump go.nhat.io/grpcmock from 0.32.0 to 0.33.0 (#1336) Bumps [go.nhat.io/grpcmock](https://github.com/nhatthm/grpcmock) from 0.32.0 to 0.33.0. - [Release notes](https://github.com/nhatthm/grpcmock/releases) - [Commits](https://github.com/nhatthm/grpcmock/compare/v0.32.0...v0.33.0) --- updated-dependencies: - dependency-name: go.nhat.io/grpcmock dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 359ce160e3..9561d75171 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 - go.nhat.io/grpcmock v0.32.0 + go.nhat.io/grpcmock v0.33.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 go.opentelemetry.io/otel v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 @@ -110,8 +110,8 @@ require ( github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/robfig/cron/v3 v3.0.1 - github.com/sergi/go-diff v1.3.1 // indirect - github.com/spf13/afero v1.14.0 // indirect + github.com/sergi/go-diff v1.4.0 // indirect + github.com/spf13/afero v1.15.0 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/testify v1.11.1 github.com/swaggest/assertjson v1.9.0 // indirect @@ -133,7 +133,7 @@ require ( golang.org/x/tools v0.38.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index a230753b7d..07a898ce09 100644 --- a/go.sum +++ b/go.sum @@ -202,17 +202,17 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= +github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -245,8 +245,8 @@ go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFX go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.nhat.io/aferomock v0.8.0 h1:jESv25NuTpA/Wga+AOKqKI1lPKdYiBYvxpIUDJWyfPM= go.nhat.io/aferomock v0.8.0/go.mod h1:thJD/9Yeo+CcIW45u6rNU8WYc1yIWdqfOSpKcGtjAXw= -go.nhat.io/grpcmock v0.32.0 h1:0qAwlE7Tc8paLbQ3TbwmucsrjW7+D3M68ozJYFWp+5c= -go.nhat.io/grpcmock v0.32.0/go.mod h1:6LzGOzY7X8cVyJBSdOMG13RqiEGDIqFy9mJedUPj5NA= +go.nhat.io/grpcmock v0.33.0 h1:R9lfxT36n4ytmSJadIVXucpsORoGVLyUiQh2yxtpWZU= +go.nhat.io/grpcmock v0.33.0/go.mod h1:f0z3MfHiMqnKLLkx+y8CiMB4xJTRWWSMKDM3Xvfl+jY= go.nhat.io/matcher/v2 v2.0.0 h1:W+rbHi0hKuZHtOQH4U5g+KwyKyfVioIxrxjoGRcUETE= go.nhat.io/matcher/v2 v2.0.0/go.mod h1:cL5oYp0M9A4L8jEGqjmUfy+k7AXVDddoVt6aYIL1r5g= go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= @@ -349,8 +349,8 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU= google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= From 1c1dd05760dcd16c13ebc81e3cd6891bc2d1d664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Wed, 29 Oct 2025 13:54:28 +0300 Subject: [PATCH 196/300] K8SPG-884: Fix shared_preload_libraries order (#1339) Co-authored-by: Viacheslav Sarzhan --- .../controller/postgrescluster/controller.go | 9 +- .../postgrescluster/controller_test.go | 115 ++++++++++++++++++ internal/pgstatmonitor/pgstatmonitor.go | 6 +- internal/pgstatstatements/pgstatstatement.go | 1 - 4 files changed, 121 insertions(+), 10 deletions(-) diff --git a/internal/controller/postgrescluster/controller.go b/internal/controller/postgrescluster/controller.go index 2dac82621a..6bd0b2e7b3 100644 --- a/internal/controller/postgrescluster/controller.go +++ b/internal/controller/postgrescluster/controller.go @@ -259,6 +259,11 @@ func (r *Reconciler) Reconcile( } pgParameters := postgres.NewParameters() + // K8SPG-577 + // K8SPG-884: pg_stat_statements must come before pg_stat_monitor + if cluster.Spec.Extensions.PGStatStatements { + pgstatstatements.PostgreSQLParameters(&pgParameters) + } // K8SPG-375 if cluster.Spec.Extensions.PGStatMonitor { pgstatmonitor.PostgreSQLParameters(&pgParameters) @@ -266,10 +271,6 @@ func (r *Reconciler) Reconcile( if cluster.Spec.Extensions.PGAudit { pgaudit.PostgreSQLParameters(&pgParameters) } - // K8SPG-577 - if cluster.Spec.Extensions.PGStatStatements { - pgstatstatements.PostgreSQLParameters(&pgParameters) - } pgbackrest.PostgreSQL(cluster, &pgParameters, backupsSpecFound) pgmonitor.PostgreSQLParameters(cluster, &pgParameters) diff --git a/internal/controller/postgrescluster/controller_test.go b/internal/controller/postgrescluster/controller_test.go index e31169f4f7..73723d63d0 100644 --- a/internal/controller/postgrescluster/controller_test.go +++ b/internal/controller/postgrescluster/controller_test.go @@ -651,4 +651,119 @@ spec: Expect(event).To(ContainSubstring("PG 12 will no longer receive updates. We recommend upgrading.")) }) }) + + Context("PG Extensions", func() { + var cluster *v1beta1.PostgresCluster + + BeforeEach(func() { + cluster = create(` +metadata: + name: test-cluster +spec: + postgresVersion: 13 + image: postgres + instances: + - name: instance1 + initContainer: + image: pg-operator + dataVolumeClaimSpec: + accessModes: + - "ReadWriteMany" + resources: + requests: + storage: 1Gi + extensions: + pgStatMonitor: false + pgStatStatements: false + pgAudit: false +`) + Expect(reconcile(cluster)).To(BeZero()) + }) + + AfterEach(func() { + ctx := context.Background() + + if cluster != nil { + Expect(client.IgnoreNotFound( + suite.Client.Delete(ctx, cluster), + )).To(Succeed()) + + // Remove finalizers, if any, so the namespace can terminate. + Expect(client.IgnoreNotFound( + suite.Client.Patch(ctx, cluster, client.RawPatch( + client.Merge.Type(), []byte(`{"metadata":{"finalizers":[]}}`))), + )).To(Succeed()) + } + }) + + getSharedLibraries := func(cfg map[string]any) string { + Expect(cfg["bootstrap"]).ToNot(BeZero()) + bootstrap, ok := cfg["bootstrap"].(map[string]any) + Expect(ok).To(BeTrue()) + + Expect(bootstrap["dcs"]).ToNot(BeZero()) + dcs, ok := bootstrap["dcs"].(map[string]any) + Expect(ok).To(BeTrue()) + + Expect(dcs["postgresql"]).ToNot(BeZero()) + postgresql, ok := dcs["postgresql"].(map[string]any) + Expect(ok).To(BeTrue()) + + Expect(postgresql["parameters"]).ToNot(BeZero()) + parameters, ok := postgresql["parameters"].(map[string]any) + Expect(ok).To(BeTrue()) + + Expect(parameters["shared_preload_libraries"]).ToNot(BeZero()) + libraries, ok := parameters["shared_preload_libraries"].(string) + Expect(ok).To(BeTrue()) + + return libraries + } + + It("appends pg_stat_monitor after pg_stat_statements", func() { + ctx := context.Background() + orig := cluster.DeepCopy() + + cluster.Spec.Extensions.PGStatMonitor = true + cluster.Spec.Extensions.PGAudit = true + + Expect(suite.Client.Patch(ctx, cluster, client.MergeFrom(orig))).To(Succeed()) + Expect(reconcile(cluster)).To(BeZero()) + Expect(cluster.Status.Patroni.SystemIdentifier).To(BeZero()) + + ccm := &corev1.ConfigMap{} + Expect(suite.Client.Get(ctx, client.ObjectKey{ + Namespace: test.Namespace.Name, Name: cluster.Name + "-config", + }, ccm)).To(Succeed()) + Expect(ccm.Data["patroni.yaml"]).ToNot(BeZero()) + + var cfg map[string]any + Expect(yaml.Unmarshal([]byte(ccm.Data["patroni.yaml"]), &cfg)).To(Succeed()) + + libraries := getSharedLibraries(cfg) + Expect(libraries).To(Equal("pg_stat_monitor,pgaudit")) + + orig = cluster.DeepCopy() + + cluster.Spec.Extensions.PGStatStatements = true + cluster.Spec.Extensions.PGStatMonitor = true + cluster.Spec.Extensions.PGAudit = true + + Expect(suite.Client.Patch(ctx, cluster, client.MergeFrom(orig))).To(Succeed()) + Expect(reconcile(cluster)).To(BeZero()) + Expect(cluster.Status.Patroni.SystemIdentifier).To(BeZero()) + + ccm = &corev1.ConfigMap{} + Expect(suite.Client.Get(ctx, client.ObjectKey{ + Namespace: test.Namespace.Name, Name: cluster.Name + "-config", + }, ccm)).To(Succeed()) + Expect(ccm.Data["patroni.yaml"]).ToNot(BeZero()) + + var cfg2 map[string]any + Expect(yaml.Unmarshal([]byte(ccm.Data["patroni.yaml"]), &cfg2)).To(Succeed()) + + libraries = getSharedLibraries(cfg2) + Expect(libraries).To(Equal("pg_stat_statements,pg_stat_monitor,pgaudit")) + }) + }) }) diff --git a/internal/pgstatmonitor/pgstatmonitor.go b/internal/pgstatmonitor/pgstatmonitor.go index 5a2d67840f..5ed6d2848c 100644 --- a/internal/pgstatmonitor/pgstatmonitor.go +++ b/internal/pgstatmonitor/pgstatmonitor.go @@ -2,7 +2,6 @@ package pgstatmonitor import ( "context" - "strings" "github.com/percona/percona-postgresql-operator/v2/internal/logging" "github.com/percona/percona-postgresql-operator/v2/internal/postgres" @@ -39,9 +38,6 @@ func DisableInPostgreSQL(ctx context.Context, exec postgres.Executor) error { } func PostgreSQLParameters(outParameters *postgres.Parameters) { - - shared := outParameters.Mandatory.Value("shared_preload_libraries") - outParameters.Mandatory.Add("shared_preload_libraries", - strings.TrimPrefix(shared+",pg_stat_monitor", ",")) + outParameters.Mandatory.AppendToList("shared_preload_libraries", "pg_stat_monitor") outParameters.Mandatory.Add("pg_stat_monitor.pgsm_query_max_len", "2048") } diff --git a/internal/pgstatstatements/pgstatstatement.go b/internal/pgstatstatements/pgstatstatement.go index 3a2e42ec6c..0f033d3d3e 100644 --- a/internal/pgstatstatements/pgstatstatement.go +++ b/internal/pgstatstatements/pgstatstatement.go @@ -38,7 +38,6 @@ func DisableInPostgreSQL(ctx context.Context, exec postgres.Executor) error { } func PostgreSQLParameters(outParameters *postgres.Parameters) { - outParameters.Mandatory.AppendToList("shared_preload_libraries", "pg_stat_statements") outParameters.Mandatory.Add("pg_stat_statements.track", "all") } From e0ac59d847faf0c0ffa21beb0a04a20bdb7527a6 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 29 Oct 2025 17:00:12 +0100 Subject: [PATCH 197/300] K8SPG-833 add "custom-envs" e2e test (#1315) --- e2e-tests/functions | 92 +++++++++++++++ e2e-tests/run-pr.csv | 1 + e2e-tests/run-release.csv | 1 + e2e-tests/tests/custom-envs/00-assert.yaml | 24 ++++ .../tests/custom-envs/00-deploy-operator.yaml | 14 +++ e2e-tests/tests/custom-envs/01-assert.yaml | 106 ++++++++++++++++++ .../tests/custom-envs/01-create-cluster.yaml | 15 +++ .../custom-envs/02-add-env-to-instance.yaml | 21 ++++ e2e-tests/tests/custom-envs/02-assert.yaml | 48 ++++++++ e2e-tests/tests/custom-envs/03-assert.yaml | 48 ++++++++ .../03-update-env-for-instance.yaml | 19 ++++ .../04-add-env-secret-to-instance.yaml | 24 ++++ e2e-tests/tests/custom-envs/04-assert.yaml | 48 ++++++++ e2e-tests/tests/custom-envs/05-assert.yaml | 48 ++++++++ .../05-update-env-in-secret-for-instance.yaml | 19 ++++ e2e-tests/tests/custom-envs/06-assert.yaml | 48 ++++++++ .../06-update-secret-for-instance.yaml | 25 +++++ e2e-tests/tests/custom-envs/07-assert.yaml | 48 ++++++++ .../07-delete-env-for-instance.yaml | 23 ++++ e2e-tests/tests/custom-envs/08-assert.yaml | 44 ++++++++ .../08-delete-secret-for-instance.yaml | 20 ++++ .../custom-envs/09-add-env-to-pgbouncer.yaml | 17 +++ e2e-tests/tests/custom-envs/09-assert.yaml | 44 ++++++++ e2e-tests/tests/custom-envs/10-assert.yaml | 44 ++++++++ .../10-update-env-for-pgbouncer.yaml | 21 ++++ .../11-add-env-secret-to-pgbouncer.yaml | 23 ++++ e2e-tests/tests/custom-envs/11-assert.yaml | 44 ++++++++ e2e-tests/tests/custom-envs/12-assert.yaml | 44 ++++++++ ...12-update-env-in-secret-for-pgbouncer.yaml | 18 +++ e2e-tests/tests/custom-envs/13-assert.yaml | 44 ++++++++ .../13-update-secret-for-pgbouncer.yaml | 25 +++++ e2e-tests/tests/custom-envs/14-assert.yaml | 44 ++++++++ .../14-delete-env-for-pgbouncer.yaml | 22 ++++ e2e-tests/tests/custom-envs/15-assert.yaml | 44 ++++++++ .../15-delete-secret-for-pgbouncer.yaml | 20 ++++ .../custom-envs/16-add-env-to-repohost.yaml | 18 +++ e2e-tests/tests/custom-envs/16-assert.yaml | 44 ++++++++ e2e-tests/tests/custom-envs/17-assert.yaml | 44 ++++++++ .../17-update-env-for-repohost.yaml | 20 ++++ .../18-add-env-secret-to-repohost.yaml | 23 ++++ e2e-tests/tests/custom-envs/18-assert.yaml | 44 ++++++++ e2e-tests/tests/custom-envs/19-assert.yaml | 44 ++++++++ .../19-update-env-in-secret-for-repohost.yaml | 20 ++++ e2e-tests/tests/custom-envs/20-assert.yaml | 44 ++++++++ .../20-update-secret-for-repohost.yaml | 27 +++++ e2e-tests/tests/custom-envs/21-assert.yaml | 44 ++++++++ .../21-delete-env-for-repohost.yaml | 21 ++++ e2e-tests/tests/custom-envs/22-assert.yaml | 44 ++++++++ .../22-delete-secret-for-repohost.yaml | 19 ++++ .../99-remove-cluster-gracefully.yaml | 21 ++++ 50 files changed, 1667 insertions(+) create mode 100644 e2e-tests/tests/custom-envs/00-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/custom-envs/01-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/01-create-cluster.yaml create mode 100644 e2e-tests/tests/custom-envs/02-add-env-to-instance.yaml create mode 100644 e2e-tests/tests/custom-envs/02-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/03-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/03-update-env-for-instance.yaml create mode 100644 e2e-tests/tests/custom-envs/04-add-env-secret-to-instance.yaml create mode 100644 e2e-tests/tests/custom-envs/04-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/05-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/05-update-env-in-secret-for-instance.yaml create mode 100644 e2e-tests/tests/custom-envs/06-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/06-update-secret-for-instance.yaml create mode 100644 e2e-tests/tests/custom-envs/07-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/07-delete-env-for-instance.yaml create mode 100644 e2e-tests/tests/custom-envs/08-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/08-delete-secret-for-instance.yaml create mode 100644 e2e-tests/tests/custom-envs/09-add-env-to-pgbouncer.yaml create mode 100644 e2e-tests/tests/custom-envs/09-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/10-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/10-update-env-for-pgbouncer.yaml create mode 100644 e2e-tests/tests/custom-envs/11-add-env-secret-to-pgbouncer.yaml create mode 100644 e2e-tests/tests/custom-envs/11-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/12-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/12-update-env-in-secret-for-pgbouncer.yaml create mode 100644 e2e-tests/tests/custom-envs/13-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/13-update-secret-for-pgbouncer.yaml create mode 100644 e2e-tests/tests/custom-envs/14-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/14-delete-env-for-pgbouncer.yaml create mode 100644 e2e-tests/tests/custom-envs/15-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/15-delete-secret-for-pgbouncer.yaml create mode 100644 e2e-tests/tests/custom-envs/16-add-env-to-repohost.yaml create mode 100644 e2e-tests/tests/custom-envs/16-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/17-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/17-update-env-for-repohost.yaml create mode 100644 e2e-tests/tests/custom-envs/18-add-env-secret-to-repohost.yaml create mode 100644 e2e-tests/tests/custom-envs/18-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/19-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/19-update-env-in-secret-for-repohost.yaml create mode 100644 e2e-tests/tests/custom-envs/20-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/20-update-secret-for-repohost.yaml create mode 100644 e2e-tests/tests/custom-envs/21-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/21-delete-env-for-repohost.yaml create mode 100644 e2e-tests/tests/custom-envs/22-assert.yaml create mode 100644 e2e-tests/tests/custom-envs/22-delete-secret-for-repohost.yaml create mode 100644 e2e-tests/tests/custom-envs/99-remove-cluster-gracefully.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index 5a87226064..08c65e8760 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -1143,3 +1143,95 @@ wait_for_generation() { fi done } + +# Reads all environment variables from a pod (single kubectl exec call) +get_envs_from_pod() { + local namespace=$1 + local pod=$2 + local container=$3 + + if [ -n "$container" ]; then + kubectl exec -n "$namespace" "$pod" -c "$container" -- printenv 2>/dev/null || true + else + kubectl exec -n "$namespace" "$pod" -- printenv 2>/dev/null || true + fi +} + +# Verifies a single variable in given env content +check_env_in_pod() { + local check_type=$1 + local pod=$2 + local var_name=$3 + local expected_value=$4 + local env_content=$5 + + local actual_value + actual_value=$(echo "$env_content" | grep -E "^${var_name}=" | cut -d'=' -f2- || true) + + if [[ "$check_type" == "add" ]]; then + if [ "$actual_value" != "$expected_value" ]; then + echo "ERROR: $var_name in $pod — expected '$expected_value', got '${actual_value:-}'" + return 1 + else + echo "OK: $var_name=$actual_value in $pod" + fi + elif [[ "$check_type" == "delete" ]]; then + if [ -n "$actual_value" ]; then + echo "ERROR: $var_name exists in $pod (should not exist)" + return 1 + else + echo "OK: $var_name deleted in $pod" + fi + else + echo "ERROR: unknown check type '$check_type'" + return 1 + fi +} + +# Checks multiple env vars in one or more components +check_envs_for_component() { + local check_type=$1 # add | delete + local component=$2 # instance | pgbouncer | repohost + local vars=("${@:3}") # everything after the 2nd argument + + case "$component" in + instance) + POD=$(kubectl get -n "${NAMESPACE}" pod -l postgres-operator.crunchydata.com/instance-set=instance1 -o 'jsonpath={.items[0].metadata.name}') + CONTAINER="" + ;; + pgbouncer) + POD=$(kubectl get -n "${NAMESPACE}" pod -l postgres-operator.crunchydata.com/role=pgbouncer -o 'jsonpath={.items[0].metadata.name}') + CONTAINER="pgbouncer" + ;; + repohost) + POD=$(kubectl get -n "${NAMESPACE}" pod -l postgres-operator.crunchydata.com/data=pgbackrest -o 'jsonpath={.items[0].metadata.name}') + CONTAINER="pgbackrest" + ;; + *) + echo "ERROR: unknown component '$component'" + return 1 + ;; + esac + + echo "Fetching environment variables for $component pod $POD..." + local env_content + env_content=$(get_envs_from_pod "${NAMESPACE}" "$POD" "$CONTAINER") + + local errors=0 + for var_entry in "${vars[@]}"; do + if [[ "$check_type" == "add" ]]; then + local var_name="${var_entry%%=*}" + local var_expected="${var_entry#*=}" + check_env_in_pod add "$POD" "$var_name" "$var_expected" "$env_content" || errors=$((errors+1)) + else + check_env_in_pod delete "$POD" "$var_entry" "" "$env_content" || errors=$((errors+1)) + fi + done + + if (( errors > 0 )); then + echo "$errors environment check(s) failed for component '$component'" + return 1 + else + echo "All environment checks passed for component '$component'" + fi +} \ No newline at end of file diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 8c480e198e..358ce44987 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -1,4 +1,5 @@ backup-enable-disable +custom-envs custom-extensions custom-tls database-init-sql diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 8c480e198e..358ce44987 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -1,4 +1,5 @@ backup-enable-disable +custom-envs custom-extensions custom-tls database-init-sql diff --git a/e2e-tests/tests/custom-envs/00-assert.yaml b/e2e-tests/tests/custom-envs/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/custom-envs/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/custom-envs/00-deploy-operator.yaml b/e2e-tests/tests/custom-envs/00-deploy-operator.yaml new file mode 100644 index 0000000000..7faf4da852 --- /dev/null +++ b/e2e-tests/tests/custom-envs/00-deploy-operator.yaml @@ -0,0 +1,14 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client + deploy_s3_secrets diff --git a/e2e-tests/tests/custom-envs/01-assert.yaml b/e2e-tests/tests/custom-envs/01-assert.yaml new file mode 100644 index 0000000000..9f767a78f3 --- /dev/null +++ b/e2e-tests/tests/custom-envs/01-assert.yaml @@ -0,0 +1,106 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-envs + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-envs + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: custom-envs-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: custom-envs + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: custom-envs + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + updatedReplicas: 1 + readyReplicas: 1 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: custom-envs + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 1 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready diff --git a/e2e-tests/tests/custom-envs/01-create-cluster.yaml b/e2e-tests/tests/custom-envs/01-create-cluster.yaml new file mode 100644 index 0000000000..2ff465910f --- /dev/null +++ b/e2e-tests/tests/custom-envs/01-create-cluster.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr \ + | yq eval ' + .spec.proxy.pgBouncer.replicas=1 | + .spec.instances[].replicas=1' - \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/custom-envs/02-add-env-to-instance.yaml b/e2e-tests/tests/custom-envs/02-add-env-to-instance.yaml new file mode 100644 index 0000000000..0a36be90fe --- /dev/null +++ b/e2e-tests/tests/custom-envs/02-add-env-to-instance.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + get_cr | yq eval ' + .spec.proxy.pgBouncer.replicas = 1 | + .spec.instances[].replicas = 1 | + .spec.instances[].env = ((.spec.instances[].env // []) + [{"name": "FIRST_ENV", "value": "1000"}, {"name": "SECOND_ENV", "value": "2000"}] | unique_by(.name)) + ' - | kubectl -n "${NAMESPACE}" apply -f - + + + sleep 10 + wait_cluster_consistency custom-envs + + check_envs_for_component add instance FIRST_ENV=1000 SECOND_ENV=2000 + diff --git a/e2e-tests/tests/custom-envs/02-assert.yaml b/e2e-tests/tests/custom-envs/02-assert.yaml new file mode 100644 index 0000000000..b03a78959c --- /dev/null +++ b/e2e-tests/tests/custom-envs/02-assert.yaml @@ -0,0 +1,48 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 2 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/03-assert.yaml b/e2e-tests/tests/custom-envs/03-assert.yaml new file mode 100644 index 0000000000..27ac4cd27f --- /dev/null +++ b/e2e-tests/tests/custom-envs/03-assert.yaml @@ -0,0 +1,48 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 3 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/03-update-env-for-instance.yaml b/e2e-tests/tests/custom-envs/03-update-env-for-instance.yaml new file mode 100644 index 0000000000..1afd19810f --- /dev/null +++ b/e2e-tests/tests/custom-envs/03-update-env-for-instance.yaml @@ -0,0 +1,19 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + kubectl -n ${NAMESPACE} get pg custom-envs -o yaml | \ + yq eval ' + .spec.instances[].env[] |= + (select(.name == "FIRST_ENV").value = "2000")' - | \ + kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + + check_envs_for_component add instance FIRST_ENV=2000 SECOND_ENV=2000 \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/04-add-env-secret-to-instance.yaml b/e2e-tests/tests/custom-envs/04-add-env-secret-to-instance.yaml new file mode 100644 index 0000000000..a5a632a4bd --- /dev/null +++ b/e2e-tests/tests/custom-envs/04-add-env-secret-to-instance.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + # Create a secret + kubectl create secret generic instance-env-secret \ + --from-literal=DB_USER=myuser \ + --from-literal=DB_PASSWORD='MyS3cretP@ss' \ + -n "${NAMESPACE}" + + kubectl get pg custom-envs -n ${NAMESPACE} -o yaml | \ + yq eval '.spec.instances[].envFrom += [{"secretRef": {"name": "instance-env-secret"}}]' - | \ + kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + check_envs_for_component add instance DB_USER=myuser DB_PASSWORD=MyS3cretP@ss + diff --git a/e2e-tests/tests/custom-envs/04-assert.yaml b/e2e-tests/tests/custom-envs/04-assert.yaml new file mode 100644 index 0000000000..98b0d2445d --- /dev/null +++ b/e2e-tests/tests/custom-envs/04-assert.yaml @@ -0,0 +1,48 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 4 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/05-assert.yaml b/e2e-tests/tests/custom-envs/05-assert.yaml new file mode 100644 index 0000000000..b2e558006d --- /dev/null +++ b/e2e-tests/tests/custom-envs/05-assert.yaml @@ -0,0 +1,48 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 5 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/05-update-env-in-secret-for-instance.yaml b/e2e-tests/tests/custom-envs/05-update-env-in-secret-for-instance.yaml new file mode 100644 index 0000000000..58ebca0fbb --- /dev/null +++ b/e2e-tests/tests/custom-envs/05-update-env-in-secret-for-instance.yaml @@ -0,0 +1,19 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n "${NAMESPACE}" patch secret instance-env-secret \ + --type='merge' \ + -p "$(echo "{\"data\": {\"DB_NEW_ENV\": \"$(printf %s 'new-value' | base64)\"}}")" + + + sleep 10 + wait_cluster_consistency custom-envs + check_envs_for_component add instance DB_USER=myuser DB_PASSWORD=MyS3cretP@ss DB_NEW_ENV=new-value + diff --git a/e2e-tests/tests/custom-envs/06-assert.yaml b/e2e-tests/tests/custom-envs/06-assert.yaml new file mode 100644 index 0000000000..a646ef2dfd --- /dev/null +++ b/e2e-tests/tests/custom-envs/06-assert.yaml @@ -0,0 +1,48 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 6 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/06-update-secret-for-instance.yaml b/e2e-tests/tests/custom-envs/06-update-secret-for-instance.yaml new file mode 100644 index 0000000000..443c98fdce --- /dev/null +++ b/e2e-tests/tests/custom-envs/06-update-secret-for-instance.yaml @@ -0,0 +1,25 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + # Create new secret with new env vars + kubectl create secret generic instance-env-secret-updated \ + --from-literal=DB_USER_NEW=myuser2 \ + --from-literal=DB_PASSWORD_NEW='NewS3cretP@ss' \ + -n "${NAMESPACE}" + + # Patch the CR to reference the new secret + kubectl get pg custom-envs -n ${NAMESPACE} -o yaml | \ + yq eval '.spec.instances[].envFrom = [{"secretRef": {"name": "instance-env-secret-updated"}}]' - | \ + kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + check_envs_for_component add instance DB_USER_NEW=myuser2 DB_PASSWORD_NEW=NewS3cretP@ss + diff --git a/e2e-tests/tests/custom-envs/07-assert.yaml b/e2e-tests/tests/custom-envs/07-assert.yaml new file mode 100644 index 0000000000..7ad6ad8b43 --- /dev/null +++ b/e2e-tests/tests/custom-envs/07-assert.yaml @@ -0,0 +1,48 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 7 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/07-delete-env-for-instance.yaml b/e2e-tests/tests/custom-envs/07-delete-env-for-instance.yaml new file mode 100644 index 0000000000..86a1059b64 --- /dev/null +++ b/e2e-tests/tests/custom-envs/07-delete-env-for-instance.yaml @@ -0,0 +1,23 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl get pg custom-envs -n ${NAMESPACE} -o yaml | \ + yq eval ' + .spec.instances[].env |= map(select(.name != "FIRST_ENV" and .name != "SECOND_ENV")) + ' - | kubectl apply -f - + + sleep 20 + wait_cluster_consistency custom-envs + check_envs_for_component delete instance FIRST_ENV SECOND_ENV + + + + + diff --git a/e2e-tests/tests/custom-envs/08-assert.yaml b/e2e-tests/tests/custom-envs/08-assert.yaml new file mode 100644 index 0000000000..0610e10a30 --- /dev/null +++ b/e2e-tests/tests/custom-envs/08-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 8 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/08-delete-secret-for-instance.yaml b/e2e-tests/tests/custom-envs/08-delete-secret-for-instance.yaml new file mode 100644 index 0000000000..1fc3c5e31c --- /dev/null +++ b/e2e-tests/tests/custom-envs/08-delete-secret-for-instance.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl get pg custom-envs -n ${NAMESPACE} -o yaml | \ + yq eval ' + .spec.instances[].envFrom = [] + ' - | kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + check_envs_for_component delete instance DB_USER_NEW DB_PASSWORD_NEW + + diff --git a/e2e-tests/tests/custom-envs/09-add-env-to-pgbouncer.yaml b/e2e-tests/tests/custom-envs/09-add-env-to-pgbouncer.yaml new file mode 100644 index 0000000000..ce43601811 --- /dev/null +++ b/e2e-tests/tests/custom-envs/09-add-env-to-pgbouncer.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + kubectl -n "${NAMESPACE}" patch pg custom-envs \ + --type merge \ + -p '{"spec":{"proxy":{"pgBouncer":{"replicas":1,"env":[{"name": "FIRST_ENV", "value": "1000"}, {"name": "SECOND_ENV", "value": "2000"}]}}}}' + + sleep 10 + wait_cluster_consistency custom-envs + + check_envs_for_component add pgbouncer FIRST_ENV=1000 SECOND_ENV=2000 \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/09-assert.yaml b/e2e-tests/tests/custom-envs/09-assert.yaml new file mode 100644 index 0000000000..1cd98b27f5 --- /dev/null +++ b/e2e-tests/tests/custom-envs/09-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 9 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/10-assert.yaml b/e2e-tests/tests/custom-envs/10-assert.yaml new file mode 100644 index 0000000000..8f5935fe9b --- /dev/null +++ b/e2e-tests/tests/custom-envs/10-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 10 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/10-update-env-for-pgbouncer.yaml b/e2e-tests/tests/custom-envs/10-update-env-for-pgbouncer.yaml new file mode 100644 index 0000000000..73de84401b --- /dev/null +++ b/e2e-tests/tests/custom-envs/10-update-env-for-pgbouncer.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n "${NAMESPACE}" get pg custom-envs -o yaml | \ + yq eval ' + .spec.proxy.pgBouncer.env[] |= + (select(.name == "FIRST_ENV").value = "2000") + ' - | kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + + check_envs_for_component add pgbouncer FIRST_ENV=2000 SECOND_ENV=2000 + diff --git a/e2e-tests/tests/custom-envs/11-add-env-secret-to-pgbouncer.yaml b/e2e-tests/tests/custom-envs/11-add-env-secret-to-pgbouncer.yaml new file mode 100644 index 0000000000..fdca41b907 --- /dev/null +++ b/e2e-tests/tests/custom-envs/11-add-env-secret-to-pgbouncer.yaml @@ -0,0 +1,23 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl create secret generic pgbouncer-env-secret \ + --from-literal=DB_USER=myuser \ + --from-literal=DB_PASSWORD='MyS3cretP@ss' \ + -n "${NAMESPACE}" + + kubectl get pg custom-envs -n "${NAMESPACE}" -o yaml | \ + yq eval ' + .spec.proxy.pgBouncer.envFrom += [{"secretRef": {"name": "pgbouncer-env-secret"}}] + ' - | kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + check_envs_for_component add pgbouncer DB_USER=myuser DB_PASSWORD=MyS3cretP@ss diff --git a/e2e-tests/tests/custom-envs/11-assert.yaml b/e2e-tests/tests/custom-envs/11-assert.yaml new file mode 100644 index 0000000000..924bdf8787 --- /dev/null +++ b/e2e-tests/tests/custom-envs/11-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 11 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/12-assert.yaml b/e2e-tests/tests/custom-envs/12-assert.yaml new file mode 100644 index 0000000000..99562c7373 --- /dev/null +++ b/e2e-tests/tests/custom-envs/12-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 12 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/12-update-env-in-secret-for-pgbouncer.yaml b/e2e-tests/tests/custom-envs/12-update-env-in-secret-for-pgbouncer.yaml new file mode 100644 index 0000000000..3348f535e3 --- /dev/null +++ b/e2e-tests/tests/custom-envs/12-update-env-in-secret-for-pgbouncer.yaml @@ -0,0 +1,18 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n "${NAMESPACE}" patch secret pgbouncer-env-secret \ + --type='merge' \ + -p "$(printf '{"data":{"DB_NEW_ENV":"%s"}}' "$(printf 'new-value' | base64)")" + + sleep 10 + wait_cluster_consistency custom-envs + check_envs_for_component add pgbouncer DB_USER=myuser DB_PASSWORD=MyS3cretP@ss DB_NEW_ENV=new-value + diff --git a/e2e-tests/tests/custom-envs/13-assert.yaml b/e2e-tests/tests/custom-envs/13-assert.yaml new file mode 100644 index 0000000000..64a58fabcb --- /dev/null +++ b/e2e-tests/tests/custom-envs/13-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 13 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/13-update-secret-for-pgbouncer.yaml b/e2e-tests/tests/custom-envs/13-update-secret-for-pgbouncer.yaml new file mode 100644 index 0000000000..d842902cb7 --- /dev/null +++ b/e2e-tests/tests/custom-envs/13-update-secret-for-pgbouncer.yaml @@ -0,0 +1,25 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl create secret generic pgbouncer-env-secret-updated \ + --from-literal=DB_USER_NEW=myuser2 \ + --from-literal=DB_PASSWORD_NEW='NewS3cretP@ss' \ + -n "${NAMESPACE}" + + + kubectl get pg custom-envs -n "${NAMESPACE}" -o yaml | \ + yq eval '.spec.proxy.pgBouncer.envFrom = [{"secretRef": {"name": "pgbouncer-env-secret-updated"}}]' - | \ + kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + + check_envs_for_component add pgbouncer DB_USER_NEW=myuser2 DB_PASSWORD_NEW=NewS3cretP@ss + diff --git a/e2e-tests/tests/custom-envs/14-assert.yaml b/e2e-tests/tests/custom-envs/14-assert.yaml new file mode 100644 index 0000000000..4ea2438b2a --- /dev/null +++ b/e2e-tests/tests/custom-envs/14-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 14 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/14-delete-env-for-pgbouncer.yaml b/e2e-tests/tests/custom-envs/14-delete-env-for-pgbouncer.yaml new file mode 100644 index 0000000000..26db738324 --- /dev/null +++ b/e2e-tests/tests/custom-envs/14-delete-env-for-pgbouncer.yaml @@ -0,0 +1,22 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n "${NAMESPACE}" get pg custom-envs -o yaml | \ + yq eval ' + .spec.proxy.pgBouncer.env |= map(select(.name != "FIRST_ENV" and .name != "SECOND_ENV")) + ' - | kubectl apply -f - + + + + sleep 30 + wait_cluster_consistency custom-envs + + check_envs_for_component delete pgbouncer FIRST_ENV SECOND_ENV + diff --git a/e2e-tests/tests/custom-envs/15-assert.yaml b/e2e-tests/tests/custom-envs/15-assert.yaml new file mode 100644 index 0000000000..8561612fd9 --- /dev/null +++ b/e2e-tests/tests/custom-envs/15-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 15 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/15-delete-secret-for-pgbouncer.yaml b/e2e-tests/tests/custom-envs/15-delete-secret-for-pgbouncer.yaml new file mode 100644 index 0000000000..dcfccae96e --- /dev/null +++ b/e2e-tests/tests/custom-envs/15-delete-secret-for-pgbouncer.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl get pg custom-envs -n "${NAMESPACE}" -o yaml | \ + yq eval ' + .spec.proxy.pgBouncer.envFrom = [] + ' - | kubectl apply -f - + + sleep 10 + wait_cluster_consistency custom-envs + + check_envs_for_component delete pgbouncer DB_USER_NEW DB_PASSWORD_NEW + diff --git a/e2e-tests/tests/custom-envs/16-add-env-to-repohost.yaml b/e2e-tests/tests/custom-envs/16-add-env-to-repohost.yaml new file mode 100644 index 0000000000..c7d7d894a1 --- /dev/null +++ b/e2e-tests/tests/custom-envs/16-add-env-to-repohost.yaml @@ -0,0 +1,18 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n "${NAMESPACE}" patch pg custom-envs \ + --type merge \ + -p '{"spec":{"backups":{"pgbackrest":{"env":[{"name": "FIRST_ENV", "value": "1000"}, {"name": "SECOND_ENV", "value": "2000"}]}}}}' + + sleep 20 + wait_cluster_consistency custom-envs + check_envs_for_component add repohost FIRST_ENV=1000 SECOND_ENV=2000 + diff --git a/e2e-tests/tests/custom-envs/16-assert.yaml b/e2e-tests/tests/custom-envs/16-assert.yaml new file mode 100644 index 0000000000..d340d9d4d9 --- /dev/null +++ b/e2e-tests/tests/custom-envs/16-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 16 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/17-assert.yaml b/e2e-tests/tests/custom-envs/17-assert.yaml new file mode 100644 index 0000000000..743d45fad4 --- /dev/null +++ b/e2e-tests/tests/custom-envs/17-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 17 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/17-update-env-for-repohost.yaml b/e2e-tests/tests/custom-envs/17-update-env-for-repohost.yaml new file mode 100644 index 0000000000..7a70e4055e --- /dev/null +++ b/e2e-tests/tests/custom-envs/17-update-env-for-repohost.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + kubectl -n ${NAMESPACE} get pg custom-envs -o yaml | \ + yq eval ' + .spec.backups.pgbackrest.env[] |= + (select(.name == "FIRST_ENV").value = "2000")' - | \ + kubectl apply -f - + + sleep 30 + wait_cluster_consistency custom-envs + + check_envs_for_component add repohost FIRST_ENV=2000 SECOND_ENV=2000 + diff --git a/e2e-tests/tests/custom-envs/18-add-env-secret-to-repohost.yaml b/e2e-tests/tests/custom-envs/18-add-env-secret-to-repohost.yaml new file mode 100644 index 0000000000..b30bd27209 --- /dev/null +++ b/e2e-tests/tests/custom-envs/18-add-env-secret-to-repohost.yaml @@ -0,0 +1,23 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl create secret generic repo-host-env-secret \ + --from-literal=DB_USER=myuser \ + --from-literal=DB_PASSWORD='MyS3cretP@ss' \ + -n "${NAMESPACE}" + + kubectl get pg custom-envs -n ${NAMESPACE} -o yaml | \ + yq eval '.spec.backups.pgbackrest.envFrom += [{"secretRef": {"name": "repo-host-env-secret"}}]' - | \ + kubectl apply -f - + + sleep 60 + wait_cluster_consistency custom-envs + + check_envs_for_component add repohost DB_USER=myuser DB_PASSWORD=MyS3cretP@ss diff --git a/e2e-tests/tests/custom-envs/18-assert.yaml b/e2e-tests/tests/custom-envs/18-assert.yaml new file mode 100644 index 0000000000..36ecbfa9ed --- /dev/null +++ b/e2e-tests/tests/custom-envs/18-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 18 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/19-assert.yaml b/e2e-tests/tests/custom-envs/19-assert.yaml new file mode 100644 index 0000000000..2af2f2d196 --- /dev/null +++ b/e2e-tests/tests/custom-envs/19-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 19 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/19-update-env-in-secret-for-repohost.yaml b/e2e-tests/tests/custom-envs/19-update-env-in-secret-for-repohost.yaml new file mode 100644 index 0000000000..3479113c28 --- /dev/null +++ b/e2e-tests/tests/custom-envs/19-update-env-in-secret-for-repohost.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n "${NAMESPACE}" patch secret repo-host-env-secret \ + --type='merge' \ + -p "$(printf '{"data":{"DB_NEW_ENV":"%s"}}' "$(printf 'new-value' | base64)")" + + + sleep 60 + wait_cluster_consistency custom-envs + + check_envs_for_component add repohost DB_USER=myuser DB_PASSWORD=MyS3cretP@ss DB_NEW_ENV=new-value + diff --git a/e2e-tests/tests/custom-envs/20-assert.yaml b/e2e-tests/tests/custom-envs/20-assert.yaml new file mode 100644 index 0000000000..f5b272baa7 --- /dev/null +++ b/e2e-tests/tests/custom-envs/20-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 20 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/20-update-secret-for-repohost.yaml b/e2e-tests/tests/custom-envs/20-update-secret-for-repohost.yaml new file mode 100644 index 0000000000..bcea8259b7 --- /dev/null +++ b/e2e-tests/tests/custom-envs/20-update-secret-for-repohost.yaml @@ -0,0 +1,27 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl create secret generic repo-host-env-secret-updated \ + --from-literal=DB_USER_NEW=myuser2 \ + --from-literal=DB_PASSWORD_NEW='NewS3cretP@ss' \ + -n "${NAMESPACE}" + + + kubectl get pg custom-envs -n "${NAMESPACE}" -o yaml | \ + yq eval '.spec.backups.pgbackrest.envFrom += [{"secretRef": {"name": "repo-host-env-secret-updated"}}]' - | \ + kubectl apply -f - + + + sleep 60 + wait_cluster_consistency custom-envs + + check_envs_for_component add repohost DB_USER_NEW=myuser2 DB_PASSWORD_NEW=NewS3cretP@ss + + diff --git a/e2e-tests/tests/custom-envs/21-assert.yaml b/e2e-tests/tests/custom-envs/21-assert.yaml new file mode 100644 index 0000000000..a90cfff6fc --- /dev/null +++ b/e2e-tests/tests/custom-envs/21-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 21 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/21-delete-env-for-repohost.yaml b/e2e-tests/tests/custom-envs/21-delete-env-for-repohost.yaml new file mode 100644 index 0000000000..35d2206295 --- /dev/null +++ b/e2e-tests/tests/custom-envs/21-delete-env-for-repohost.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl -n ${NAMESPACE} get pg custom-envs -o yaml | \ + yq eval ' + .spec.backups.pgbackrest.env |= map(select(.name != "FIRST_ENV" and .name != "SECOND_ENV")) + ' - | kubectl apply -f - + + + sleep 60 + wait_cluster_consistency custom-envs + + check_envs_for_component delete repohost FIRST_ENV SECOND_ENV + diff --git a/e2e-tests/tests/custom-envs/22-assert.yaml b/e2e-tests/tests/custom-envs/22-assert.yaml new file mode 100644 index 0000000000..f1aa497c70 --- /dev/null +++ b/e2e-tests/tests/custom-envs/22-assert.yaml @@ -0,0 +1,44 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: custom-envs + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: custom-envs + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 22 + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: custom-envs +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/22-delete-secret-for-repohost.yaml b/e2e-tests/tests/custom-envs/22-delete-secret-for-repohost.yaml new file mode 100644 index 0000000000..6cd7535b5e --- /dev/null +++ b/e2e-tests/tests/custom-envs/22-delete-secret-for-repohost.yaml @@ -0,0 +1,19 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl get pg custom-envs -n ${NAMESPACE} -o yaml | \ + yq eval ' + .spec.backups.pgbackrest.envFrom = [] + ' - | kubectl apply -f - + + sleep 60 + wait_cluster_consistency custom-envs + + check_envs_for_component delete repohost DB_USER_NEW DB_PASSWORD_NEW \ No newline at end of file diff --git a/e2e-tests/tests/custom-envs/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/custom-envs/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..74eca26884 --- /dev/null +++ b/e2e-tests/tests/custom-envs/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: one-pod +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: one-pod +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 From 817cf8cdf5af96db761af95359d1ed92ad7b8da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20G=C3=BCne=C5=9F?= Date: Thu, 30 Oct 2025 13:46:23 +0300 Subject: [PATCH 198/300] K8SPG-876: Log commands before execing them in containers (#1341) --- internal/controller/runtime/pod_client.go | 3 +++ percona/clientcmd/clientcmd.go | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/internal/controller/runtime/pod_client.go b/internal/controller/runtime/pod_client.go index 4122303bf5..597de85a24 100644 --- a/internal/controller/runtime/pod_client.go +++ b/internal/controller/runtime/pod_client.go @@ -15,6 +15,7 @@ import ( "k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/util/flowcontrol" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" + logf "sigs.k8s.io/controller-runtime/pkg/log" ) // podExecutor runs command on container in pod in namespace. Non-nil streams @@ -62,6 +63,8 @@ func NewPodExecutor(config *rest.Config) (podExecutor, error) { exec, err := remotecommand.NewSPDYExecutor(configCopy, "POST", request.URL()) + log := logf.FromContext(ctx) + log.V(1).Info("Running command in pod", "pod", pod, "container", container, "command", command) if err == nil { err = exec.StreamWithContext(ctx, remotecommand.StreamOptions{ Stdin: stdin, diff --git a/percona/clientcmd/clientcmd.go b/percona/clientcmd/clientcmd.go index 411e1a1551..879d281e1d 100644 --- a/percona/clientcmd/clientcmd.go +++ b/percona/clientcmd/clientcmd.go @@ -13,6 +13,7 @@ import ( "k8s.io/client-go/tools/remotecommand" "k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/retry" + logf "sigs.k8s.io/controller-runtime/pkg/log" ) type Client struct { @@ -73,6 +74,9 @@ func (c *Client) Exec(ctx context.Context, pod *corev1.Pod, containerName string return errors.Wrap(err, "failed to create executor") } + log := logf.FromContext(ctx) + log.V(1).Info("Running command in pod", "pod", pod.Name, "container", containerName, "command", command) + retryErr := retry.OnError(retry.DefaultRetry, func(err error) bool { return true // Retry on all errors }, func() error { From bd567dabd281684e6842532fe83828351d2ae08a Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Mon, 3 Nov 2025 16:19:26 +0200 Subject: [PATCH 199/300] K8SPG-882 determine patroni version without using the special patroni version check pod (#1334) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * K8SPG-882 determine patroni version without using the special patroni version check pod * improve primary pod * fix imports * fix failed test * increase timeout on test upgrade-minor when creating the cluster * make custom annotation working only for 2.7 and older * update cr * early return * make annotations great again * reconcile one more time * fixes --------- Co-authored-by: Viacheslav Sarzhan Co-authored-by: Ege Güneş --- deploy/cr.yaml | 2 +- .../upgrade-minor/01-create-cluster.yaml | 2 +- percona/controller/pgcluster/controller.go | 234 +---------- .../controller/pgcluster/controller_test.go | 226 +---------- .../controller/pgcluster/patroniversion.go | 319 +++++++++++++++ .../pgcluster/patroniversion_test.go | 186 +++++++++ percona/naming/prefix.go | 4 - percona/postgres/common.go | 22 +- percona/postgres/common_test.go | 380 ++++++++++++++++++ percona/watcher/wal_test.go | 4 +- 10 files changed, 906 insertions(+), 473 deletions(-) create mode 100644 percona/controller/pgcluster/patroniversion.go create mode 100644 percona/controller/pgcluster/patroniversion_test.go create mode 100644 percona/postgres/common_test.go diff --git a/deploy/cr.yaml b/deploy/cr.yaml index ac61fd2788..e055bc6f38 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -3,7 +3,7 @@ kind: PerconaPGCluster metadata: name: cluster1 # annotations: -# pgv2.percona.com/custom-patroni-version: "4" +# test-annotation: value # finalizers: # - percona.com/delete-pvc # - percona.com/delete-ssl diff --git a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml index 358a147dac..9b96bfe43c 100644 --- a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep -timeout: 10 +timeout: 100 commands: - script: |- set -o errexit diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 87720b05f5..a7685ecde8 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -1,7 +1,6 @@ package pgcluster import ( - "bytes" "context" "crypto/md5" "fmt" @@ -11,21 +10,17 @@ import ( "strings" "time" - gover "github.com/hashicorp/go-version" "github.com/pkg/errors" "go.opentelemetry.io/otel/trace" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/retry" "k8s.io/client-go/util/workqueue" - "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -39,11 +34,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" - "github.com/percona/percona-postgresql-operator/v2/internal/initialize" "github.com/percona/percona-postgresql-operator/v2/internal/logging" "github.com/percona/percona-postgresql-operator/v2/internal/naming" "github.com/percona/percona-postgresql-operator/v2/internal/postgres" - "github.com/percona/percona-postgresql-operator/v2/percona/clientcmd" perconaController "github.com/percona/percona-postgresql-operator/v2/percona/controller" "github.com/percona/percona-postgresql-operator/v2/percona/extensions" "github.com/percona/percona-postgresql-operator/v2/percona/k8s" @@ -272,7 +265,7 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "ensure finalizers") } - if err := r.reconcilePatroniVersionCheck(ctx, cr); err != nil { + if err := r.reconcilePatroniVersion(ctx, cr); err != nil { if errors.Is(err, errPatroniVersionCheckWait) { return reconcile.Result{ RequeueAfter: 5 * time.Second, @@ -366,231 +359,6 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return ctrl.Result{}, nil } -var errPatroniVersionCheckWait = errors.New("waiting for pod to initialize") - -func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context, cr *v2.PerconaPGCluster) error { - if cr.Annotations == nil { - cr.Annotations = make(map[string]string) - } - - if patroniVersion, ok := cr.Annotations[pNaming.AnnotationCustomPatroniVersion]; ok { - patroniVersionUpdateFunc := func() error { - cluster := &v2.PerconaPGCluster{} - if err := r.Client.Get(ctx, types.NamespacedName{ - Name: cr.Name, - Namespace: cr.Namespace, - }, cluster); err != nil { - return errors.Wrap(err, "get PerconaPGCluster") - } - - orig := cluster.DeepCopy() - - cluster.Status.Patroni.Version = patroniVersion - cluster.Status.PatroniVersion = patroniVersion - - if err := r.Client.Status().Patch(ctx, cluster.DeepCopy(), client.MergeFrom(orig)); err != nil { - return errors.Wrap(err, "failed to patch patroni version") - } - - err := r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) - if err != nil { - return errors.Wrap(err, "failed to patch patroni version annotation") - } - - return nil - } - - // To ensure that the update was done given that conflicts can be caused by - // other code making unrelated updates to the same resource at the same time. - if err := retry.RetryOnConflict(retry.DefaultRetry, patroniVersionUpdateFunc); err != nil { - return errors.Wrap(err, "failed to patch patroni version") - } - return nil - } - - imageIDs, err := r.instanceImageIDs(ctx, cr) - if err != nil { - return errors.Wrap(err, "get image IDs") - } - - // If the imageIDs slice contains the imageID from the status, we skip checking the Patroni version. - // This ensures that the Patroni version is only checked after all pods have been updated. - if cr.CompareVersion("2.8.0") >= 0 { - if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.Patroni.Version != "" { - err = r.patchPatroniVersionAnnotation(ctx, cr, cr.Status.Patroni.Version) - if err != nil { - return errors.Wrap(err, "failed to patch patroni version annotation") - } - return nil - } - } else { - if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.PatroniVersion != "" { - err = r.patchPatroniVersionAnnotation(ctx, cr, cr.Status.PatroniVersion) - if err != nil { - return errors.Wrap(err, "failed to patch patroni version annotation") - } - return nil - } - } - - meta := metav1.ObjectMeta{ - Name: cr.Name + "-patroni-version-check", - Namespace: cr.Namespace, - } - - p := &corev1.Pod{ - ObjectMeta: meta, - } - - err = r.Client.Get(ctx, client.ObjectKeyFromObject(p), p) - if client.IgnoreNotFound(err) != nil { - return errors.Wrap(err, "failed to get patroni version check pod") - } - if k8serrors.IsNotFound(err) { - if len(cr.Spec.InstanceSets) == 0 { - return errors.New(".spec.instances is a required value") // shouldn't happen as the value is required in the crd.yaml - } - - // Using minimal resources since the patroni version check pod is performing a very simple - // operation i.e. "patronictl version" - resources := corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("100m"), - corev1.ResourceMemory: resource.MustParse("64Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("50m"), - corev1.ResourceMemory: resource.MustParse("32Mi"), - }, - } - - p = &corev1.Pod{ - ObjectMeta: meta, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: pNaming.ContainerPatroniVersionCheck, - Image: cr.PostgresImage(), - Command: []string{ - "bash", - }, - Args: []string{ - "-c", "sleep 60", - }, - Resources: resources, - SecurityContext: initialize.RestrictedSecurityContext(cr.CompareVersion("2.8.0") >= 0), - }, - }, - SecurityContext: cr.Spec.InstanceSets[0].SecurityContext, - Affinity: cr.Spec.InstanceSets[0].Affinity, - TerminationGracePeriodSeconds: ptr.To(int64(5)), - ImagePullSecrets: cr.Spec.ImagePullSecrets, - Resources: &resources, - }, - } - - if err := controllerutil.SetControllerReference(cr, p, r.Client.Scheme()); err != nil { - return errors.Wrap(err, "set controller reference") - } - if err := r.Client.Create(ctx, p); client.IgnoreAlreadyExists(err) != nil { - return errors.Wrap(err, "failed to create pod to check patroni version") - } - - return errPatroniVersionCheckWait - } - - if p.Status.Phase != corev1.PodRunning { - return errPatroniVersionCheckWait - } - - var stdout, stderr bytes.Buffer - execCli, err := clientcmd.NewClient() - if err != nil { - return errors.Wrap(err, "failed to create exec client") - } - b := wait.Backoff{ - Duration: 5 * time.Second, - Factor: 1.0, - Steps: 12, - Cap: time.Minute, - } - if err := retry.OnError(b, func(err error) bool { return err != nil && strings.Contains(err.Error(), "container not found") }, func() error { - return execCli.Exec(ctx, p, pNaming.ContainerPatroniVersionCheck, nil, &stdout, &stderr, "patronictl", "version") - }); err != nil { - return errors.Wrap(err, "exec") - } - - patroniVersion := strings.TrimSpace(strings.TrimPrefix(stdout.String(), "patronictl version ")) - - if _, err := gover.NewVersion(patroniVersion); err != nil { - return errors.Wrap(err, "failed to validate patroni version") - } - - orig := cr.DeepCopy() - - cr.Status.Patroni.Version = patroniVersion - cr.Status.PatroniVersion = patroniVersion - cr.Status.Postgres.Version = cr.Spec.PostgresVersion - cr.Status.Postgres.ImageID = getImageIDFromPod(p, pNaming.ContainerPatroniVersionCheck) - - if err := r.Client.Status().Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { - return errors.Wrap(err, "failed to patch patroni version") - } - - err = r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) - if err != nil { - return errors.Wrap(err, "failed to patch patroni version annotation") - } - - if err := r.Client.Delete(ctx, p); err != nil { - return errors.Wrap(err, "failed to delete patroni version check pod") - } - - return nil -} - -func (r *PGClusterReconciler) patchPatroniVersionAnnotation(ctx context.Context, cr *v2.PerconaPGCluster, patroniVersion string) error { - orig := cr.DeepCopy() - cr.Annotations[pNaming.AnnotationPatroniVersion] = patroniVersion - if err := r.Client.Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { - return errors.Wrap(err, "failed to patch the pg cluster") - } - return nil -} - -func (r *PGClusterReconciler) instanceImageIDs(ctx context.Context, cr *v2.PerconaPGCluster) ([]string, error) { - pods := new(corev1.PodList) - instances, err := naming.AsSelector(naming.ClusterInstances(cr.Name)) - if err != nil { - return nil, errors.Wrap(err, "failed to create a selector for instance pods") - } - if err = r.Client.List(ctx, pods, client.InNamespace(cr.Namespace), client.MatchingLabelsSelector{Selector: instances}); err != nil { - return nil, errors.Wrap(err, "failed to list instances") - } - - // Collecting all image IDs from instance pods. Under normal conditions, this slice will contain a single image ID, as all pods typically use the same image. - // During an image update, it may contain multiple different image IDs as the update progresses. - var imageIDs []string - for _, pod := range pods.Items { - imageID := getImageIDFromPod(&pod, naming.ContainerDatabase) - if imageID != "" && !slices.Contains(imageIDs, imageID) { - imageIDs = append(imageIDs, imageID) - } - } - - return imageIDs, nil -} - -func getImageIDFromPod(pod *corev1.Pod, containerName string) string { - idx := slices.IndexFunc(pod.Status.ContainerStatuses, func(s corev1.ContainerStatus) bool { - return s.Name == containerName - }) - if idx == -1 { - return "" - } - return pod.Status.ContainerStatuses[idx].ImageID -} - func (r *PGClusterReconciler) reconcileTLS(ctx context.Context, cr *v2.PerconaPGCluster) error { if err := r.validateTLS(ctx, cr); err != nil { return errors.Wrap(err, "validate TLS") diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 5e39b24579..30de7aece2 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -2025,231 +2025,6 @@ var _ = Describe("ServiceAccount early creation", Ordered, func() { }) }) -var _ = Describe("patroni version check", Ordered, func() { - ctx := context.Background() - - const crName = "patroni-version-test" - const ns = crName - crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} - - namespace := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: crName, - Namespace: ns, - }, - } - - BeforeAll(func() { - By("Creating the Namespace to perform the tests") - err := k8sClient.Create(ctx, namespace) - Expect(err).To(Not(HaveOccurred())) - }) - - AfterAll(func() { - By("Deleting the Namespace to perform the tests") - _ = k8sClient.Delete(ctx, namespace) - }) - - Context("With custom patroni version annotation", func() { - cr, err := readDefaultCR(crName, ns) - It("should read default cr.yaml", func() { - Expect(err).NotTo(HaveOccurred()) - }) - - It("should create PerconaPGCluster with custom patroni version", func() { - if cr.Annotations == nil { - cr.Annotations = make(map[string]string) - } - cr.Annotations[pNaming.AnnotationCustomPatroniVersion] = "3.2.1" - - status := cr.Status - Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) - cr.Status = status - Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) - }) - - It("should successfully reconcile patroni version check", func() { - reconcilerInstance := reconciler(cr) - err := reconcilerInstance.reconcilePatroniVersionCheck(ctx, cr) - Expect(err).NotTo(HaveOccurred()) - }) - - It("should copy custom patroni version to status", func() { - updatedCR := &v2.PerconaPGCluster{} - Expect(k8sClient.Get(ctx, crNamespacedName, updatedCR)).Should(Succeed()) - - Expect(updatedCR.Status.Patroni.Version).To(Equal("3.2.1")) - Expect(updatedCR.Status.PatroniVersion).To(Equal("3.2.1")) - Expect(updatedCR.Annotations[pNaming.AnnotationPatroniVersion]).To(Equal("3.2.1")) - }) - }) - - Context("Without custom patroni version annotation", func() { - const crName2 = "patroni-version-test-2" - const ns2 = crName2 - crNamespacedName2 := types.NamespacedName{Name: crName2, Namespace: ns2} - - namespace2 := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: crName2, - Namespace: ns2, - }, - } - - BeforeAll(func() { - By("Creating the second namespace") - err := k8sClient.Create(ctx, namespace2) - Expect(err).To(Not(HaveOccurred())) - }) - - AfterAll(func() { - By("Deleting the second namespace") - _ = k8sClient.Delete(ctx, namespace2) - }) - - cr2, err := readDefaultCR(crName2, ns2) - It("should read default cr.yaml", func() { - Expect(err).NotTo(HaveOccurred()) - }) - - It("should create PerconaPGCluster without custom patroni version annotation", func() { - if cr2.Annotations == nil { - cr2.Annotations = make(map[string]string) - } - delete(cr2.Annotations, pNaming.AnnotationCustomPatroniVersion) - - uid := int64(1001) - cr2.Spec.InstanceSets[0].SecurityContext = &corev1.PodSecurityContext{ - RunAsUser: &uid, - } - cr2.Spec.InstanceSets[0].Affinity = &corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - PreferredDuringSchedulingIgnoredDuringExecution: []corev1.PreferredSchedulingTerm{ - { - Weight: int32(1), - }, - }, - }, - } - cr2.Spec.ImagePullSecrets = []corev1.LocalObjectReference{ - {Name: "test-pull-secret"}, - } - - cr2.Status.Patroni.Version = "3.1.0" - cr2.Status.PatroniVersion = "3.1.0" - cr2.Status.Postgres.ImageID = "some-image-id" - cr2.Annotations[pNaming.AnnotationPatroniVersion] = "3.1.0" - - status := cr2.Status - Expect(k8sClient.Create(ctx, cr2)).Should(Succeed()) - cr2.Status = status - Expect(k8sClient.Status().Update(ctx, cr2)).Should(Succeed()) - - pod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: cr2.Name + "-instance-pod", - Namespace: cr2.Namespace, - Labels: map[string]string{ - "postgres-operator.crunchydata.com/cluster": cr2.Name, - "postgres-operator.crunchydata.com/instance": "instance", - }, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "database", - Image: "postgres:16", - }, - }, - }, - } - Expect(k8sClient.Create(ctx, pod)).Should(Succeed()) - - pod.Status = corev1.PodStatus{ - Phase: corev1.PodRunning, - ContainerStatuses: []corev1.ContainerStatus{ - { - Name: "database", - ImageID: "postgres:16", - }, - }, - } - Expect(k8sClient.Status().Update(ctx, pod)).Should(Succeed()) - }) - - It("should create patroni version check pod and return errPatroniVersionCheckWait", func() { - reconcilerInstance := reconciler(cr2) - err := reconcilerInstance.reconcilePatroniVersionCheck(ctx, cr2) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("waiting for pod to initialize")) - }) - - It("should have created patroni version check pod with correct configuration", func() { - podName := cr2.Name + "-patroni-version-check" - pod := &corev1.Pod{} - err = k8sClient.Get(ctx, types.NamespacedName{Name: podName, Namespace: cr2.Namespace}, pod) - Expect(err).NotTo(HaveOccurred()) - - Expect(pod.Spec.Containers).To(HaveLen(1)) - Expect(pod.Spec.Containers[0].Name).To(Equal(pNaming.ContainerPatroniVersionCheck)) - Expect(pod.Spec.Containers[0].Image).To(Equal(cr2.Spec.Image)) - Expect(pod.Spec.Containers[0].Command).To(Equal([]string{"bash"})) - Expect(pod.Spec.Containers[0].Args).To(Equal([]string{"-c", "sleep 60"})) - Expect(pod.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("100m"), - corev1.ResourceMemory: resource.MustParse("64Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("50m"), - corev1.ResourceMemory: resource.MustParse("32Mi"), - }, - })) - Expect(pod.Spec.Resources).To(Equal(&corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("100m"), - corev1.ResourceMemory: resource.MustParse("64Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("50m"), - corev1.ResourceMemory: resource.MustParse("32Mi"), - }, - })) - - uid := int64(1001) - expectedSecurityContext := &corev1.PodSecurityContext{ - RunAsUser: &uid, - } - expectedImagePullSecrets := []corev1.LocalObjectReference{ - {Name: "test-pull-secret"}, - } - expectedAffinity := &corev1.Affinity{ - NodeAffinity: &corev1.NodeAffinity{ - PreferredDuringSchedulingIgnoredDuringExecution: []corev1.PreferredSchedulingTerm{ - { - Weight: int32(1), - }, - }, - }, - } - - Expect(pod.Spec.SecurityContext).To(Equal(expectedSecurityContext)) - Expect(pod.Spec.TerminationGracePeriodSeconds).To(Equal(ptr.To(int64(5)))) - Expect(pod.Spec.ImagePullSecrets).To(Equal(expectedImagePullSecrets)) - Expect(pod.Spec.Affinity).To(Equal(expectedAffinity)) - }) - - It("should preserve existing patroni version in annotation", func() { - updatedCR := &v2.PerconaPGCluster{} - Expect(k8sClient.Get(ctx, crNamespacedName2, updatedCR)).Should(Succeed()) - - Expect(updatedCR.Status.Patroni.Version).To(Equal("3.1.0")) - Expect(updatedCR.Status.PatroniVersion).To(Equal("3.1.0")) - Expect(updatedCR.Annotations[pNaming.AnnotationPatroniVersion]).To(Equal("3.1.0")) - }) - }) -}) - var _ = Describe("CR Validations", Ordered, func() { ctx := context.Background() const crName = "cr-validation" @@ -2491,6 +2266,7 @@ var _ = Describe("Init Container", Ordered, func() { }) cr, err := readDefaultCR(crName, ns) + cr.Spec.CRVersion = "2.7.0" It("should read defautl cr.yaml", func() { Expect(err).NotTo(HaveOccurred()) }) diff --git a/percona/controller/pgcluster/patroniversion.go b/percona/controller/pgcluster/patroniversion.go new file mode 100644 index 0000000000..bb305cb997 --- /dev/null +++ b/percona/controller/pgcluster/patroniversion.go @@ -0,0 +1,319 @@ +package pgcluster + +import ( + "bytes" + "context" + "slices" + "strings" + "time" + + gover "github.com/hashicorp/go-version" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/util/retry" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "github.com/percona/percona-postgresql-operator/v2/internal/initialize" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/clientcmd" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" +) + +var errPatroniVersionCheckWait = errors.New("waiting for pod to initialize") + +func (r *PGClusterReconciler) reconcilePatroniVersion(ctx context.Context, cr *v2.PerconaPGCluster) error { + if cr.Annotations == nil { + cr.Annotations = make(map[string]string) + } + if cr.CompareVersion("2.7.0") <= 0 { + if patroniVersion, ok := cr.Annotations[pNaming.AnnotationCustomPatroniVersion]; ok { + err := r.handleCustomPatroniVersionAnnotation(ctx, cr, patroniVersion) + if err != nil { + return errors.Wrap(err, "handle patroni annotation") + } + return nil + } + } + + // Starting from version 2.8.0, the patroni version check pod should not be executed. + if cr.CompareVersion("2.8.0") >= 0 { + pods, err := r.getInstancePods(ctx, cr) + if err != nil { + return errors.Wrap(err, "failed to get instance pods") + } + if len(pods.Items) == 0 { + return errors.Wrap(err, "instance pods not available") + } + + p := pods.Items[0] + + if p.Status.Phase != corev1.PodRunning { + return errPatroniVersionCheckWait + } + + patroniVersion, err := r.getPatroniVersion(ctx, &p, naming.ContainerDatabase) + if err != nil { + return errors.Wrap(err, "failed to get patroni version") + } + + orig := cr.DeepCopy() + + cr.Status.Patroni.Version = patroniVersion + cr.Status.PatroniVersion = patroniVersion + cr.Status.Postgres.Version = cr.Spec.PostgresVersion + cr.Status.Postgres.ImageID = getImageIDFromPod(&p, naming.ContainerDatabase) + + if err := r.Client.Status().Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "failed to patch patroni version") + } + + err = r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + + return nil + } + + imageIDs, err := r.instanceImageIDs(ctx, cr) + if err != nil { + return errors.Wrap(err, "get image IDs") + } + + // If the imageIDs slice contains the imageID from the status, we skip checking the Patroni version. + // This ensures that the Patroni version is only checked after all pods have been updated. + if cr.CompareVersion("2.8.0") >= 0 { + if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.Patroni.Version != "" { + err = r.patchPatroniVersionAnnotation(ctx, cr, cr.Status.Patroni.Version) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + return nil + } + } else { + if (len(imageIDs) == 0 || slices.Contains(imageIDs, cr.Status.Postgres.ImageID)) && cr.Status.PatroniVersion != "" { + err = r.patchPatroniVersionAnnotation(ctx, cr, cr.Status.PatroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + return nil + } + } + + meta := metav1.ObjectMeta{ + Name: cr.Name + "-patroni-version-check", + Namespace: cr.Namespace, + } + + p := &corev1.Pod{ + ObjectMeta: meta, + } + + err = r.Client.Get(ctx, client.ObjectKeyFromObject(p), p) + if client.IgnoreNotFound(err) != nil { + return errors.Wrap(err, "failed to get patroni version check pod") + } + if k8serrors.IsNotFound(err) { + if len(cr.Spec.InstanceSets) == 0 { + return errors.New(".spec.instances is a required value") // shouldn't happen as the value is required in the crd.yaml + } + + // Using minimal resources since the patroni version check pod is performing a very simple + // operation i.e. "patronictl version" + resources := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + } + + p = &corev1.Pod{ + ObjectMeta: meta, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: pNaming.ContainerPatroniVersionCheck, + Image: cr.PostgresImage(), + Command: []string{ + "bash", + }, + Args: []string{ + "-c", "sleep 60", + }, + Resources: resources, + SecurityContext: initialize.RestrictedSecurityContext(cr.CompareVersion("2.8.0") >= 0), + }, + }, + SecurityContext: cr.Spec.InstanceSets[0].SecurityContext, + Affinity: cr.Spec.InstanceSets[0].Affinity, + TerminationGracePeriodSeconds: ptr.To(int64(5)), + ImagePullSecrets: cr.Spec.ImagePullSecrets, + Resources: &resources, + }, + } + + if err := controllerutil.SetControllerReference(cr, p, r.Client.Scheme()); err != nil { + return errors.Wrap(err, "set controller reference") + } + if err := r.Client.Create(ctx, p); client.IgnoreAlreadyExists(err) != nil { + return errors.Wrap(err, "failed to create pod to check patroni version") + } + + return errPatroniVersionCheckWait + } + + if p.Status.Phase != corev1.PodRunning { + return errPatroniVersionCheckWait + } + + patroniVersion, err := r.getPatroniVersion(ctx, p, pNaming.ContainerPatroniVersionCheck) + if err != nil { + return errors.Wrap(err, "failed to get patroni version") + } + + orig := cr.DeepCopy() + + cr.Status.Patroni.Version = patroniVersion + cr.Status.PatroniVersion = patroniVersion + cr.Status.Postgres.Version = cr.Spec.PostgresVersion + cr.Status.Postgres.ImageID = getImageIDFromPod(p, pNaming.ContainerPatroniVersionCheck) + + if err := r.Client.Status().Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "failed to patch patroni version") + } + + err = r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + + if err := r.Client.Delete(ctx, p); err != nil { + return errors.Wrap(err, "failed to delete patroni version check pod") + } + + return nil +} + +func (r *PGClusterReconciler) getPatroniVersion(ctx context.Context, pod *corev1.Pod, containerName string) (string, error) { + var stdout, stderr bytes.Buffer + execCli, err := clientcmd.NewClient() + if err != nil { + return "", errors.Wrap(err, "failed to create exec client") + } + b := wait.Backoff{ + Duration: 5 * time.Second, + Factor: 1.0, + Steps: 12, + Cap: time.Minute, + } + if err := retry.OnError(b, func(err error) bool { return err != nil && strings.Contains(err.Error(), "container not found") }, func() error { + return execCli.Exec(ctx, pod, containerName, nil, &stdout, &stderr, "patronictl", "version") + }); err != nil { + return "", errors.Wrap(err, "exec") + } + + patroniVersion := strings.TrimSpace(strings.TrimPrefix(stdout.String(), "patronictl version ")) + + if _, err := gover.NewVersion(patroniVersion); err != nil { + return "", errors.Wrap(err, "failed to validate patroni version") + } + + return patroniVersion, nil +} + +func (r *PGClusterReconciler) handleCustomPatroniVersionAnnotation(ctx context.Context, cr *v2.PerconaPGCluster, patroniVersion string) error { + patroniVersionUpdateFunc := func() error { + cluster := &v2.PerconaPGCluster{} + if err := r.Client.Get(ctx, types.NamespacedName{ + Name: cr.Name, + Namespace: cr.Namespace, + }, cluster); err != nil { + return errors.Wrap(err, "get PerconaPGCluster") + } + + orig := cluster.DeepCopy() + + cluster.Status.Patroni.Version = patroniVersion + cluster.Status.PatroniVersion = patroniVersion + + if err := r.Client.Status().Patch(ctx, cluster.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "failed to patch patroni version") + } + + err := r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + + return nil + } + + // To ensure that the update was done given that conflicts can be caused by + // other code making unrelated updates to the same resource at the same time. + if err := retry.RetryOnConflict(retry.DefaultRetry, patroniVersionUpdateFunc); err != nil { + return errors.Wrap(err, "failed to patch patroni version") + } + return nil +} + +func (r *PGClusterReconciler) patchPatroniVersionAnnotation(ctx context.Context, cr *v2.PerconaPGCluster, patroniVersion string) error { + orig := cr.DeepCopy() + cr.Annotations[pNaming.AnnotationPatroniVersion] = patroniVersion + if err := r.Client.Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "failed to patch the pg cluster") + } + return nil +} + +func (r *PGClusterReconciler) instanceImageIDs(ctx context.Context, cr *v2.PerconaPGCluster) ([]string, error) { + pods, err := r.getInstancePods(ctx, cr) + if err != nil { + return nil, errors.Wrap(err, "failed to get instance pods") + } + + // Collecting all image IDs from instance pods. Under normal conditions, this slice will contain a single image ID, as all pods typically use the same image. + // During an image update, it may contain multiple different image IDs as the update progresses. + var imageIDs []string + for _, pod := range pods.Items { + imageID := getImageIDFromPod(&pod, naming.ContainerDatabase) + if imageID != "" && !slices.Contains(imageIDs, imageID) { + imageIDs = append(imageIDs, imageID) + } + } + + return imageIDs, nil +} + +func (r *PGClusterReconciler) getInstancePods(ctx context.Context, cr *v2.PerconaPGCluster) (*corev1.PodList, error) { + pods := new(corev1.PodList) + instances, err := naming.AsSelector(naming.ClusterInstances(cr.Name)) + if err != nil { + return nil, errors.Wrap(err, "failed to create a selector for instance pods") + } + if err = r.Client.List(ctx, pods, client.InNamespace(cr.Namespace), client.MatchingLabelsSelector{Selector: instances}); err != nil { + return nil, errors.Wrap(err, "failed to list instances") + } + return pods, nil +} + +func getImageIDFromPod(pod *corev1.Pod, containerName string) string { + idx := slices.IndexFunc(pod.Status.ContainerStatuses, func(s corev1.ContainerStatus) bool { + return s.Name == containerName + }) + if idx == -1 { + return "" + } + return pod.Status.ContainerStatuses[idx].ImageID +} diff --git a/percona/controller/pgcluster/patroniversion_test.go b/percona/controller/pgcluster/patroniversion_test.go new file mode 100644 index 0000000000..bcd876d3bb --- /dev/null +++ b/percona/controller/pgcluster/patroniversion_test.go @@ -0,0 +1,186 @@ +package pgcluster + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" + + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" +) + +var _ = Describe("patroni version check", Ordered, func() { + ctx := context.Background() + + Context("Without custom patroni version annotation for cr version <=2.7", func() { + const crName2 = "patroni-version-test-2" + const ns2 = crName2 + crNamespacedName2 := types.NamespacedName{Name: crName2, Namespace: ns2} + + namespace2 := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: crName2, + Namespace: ns2, + }, + } + + BeforeAll(func() { + By("Creating the second namespace") + err := k8sClient.Create(ctx, namespace2) + Expect(err).To(Not(HaveOccurred())) + }) + + AfterAll(func() { + By("Deleting the second namespace") + _ = k8sClient.Delete(ctx, namespace2) + }) + + cr2, err := readDefaultCR(crName2, ns2) + cr2.Spec.CRVersion = "2.7.0" + It("should read default cr.yaml", func() { + Expect(err).NotTo(HaveOccurred()) + }) + + It("should create PerconaPGCluster without custom patroni version annotation", func() { + if cr2.Annotations == nil { + cr2.Annotations = make(map[string]string) + } + delete(cr2.Annotations, pNaming.AnnotationCustomPatroniVersion) + + uid := int64(1001) + cr2.Spec.InstanceSets[0].SecurityContext = &corev1.PodSecurityContext{ + RunAsUser: &uid, + } + cr2.Spec.InstanceSets[0].Affinity = &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []corev1.PreferredSchedulingTerm{ + { + Weight: int32(1), + }, + }, + }, + } + cr2.Spec.ImagePullSecrets = []corev1.LocalObjectReference{ + {Name: "test-pull-secret"}, + } + + cr2.Status.Patroni.Version = "3.1.0" + cr2.Status.PatroniVersion = "3.1.0" + cr2.Status.Postgres.ImageID = "some-image-id" + cr2.Annotations[pNaming.AnnotationPatroniVersion] = "3.1.0" + + status := cr2.Status + Expect(k8sClient.Create(ctx, cr2)).Should(Succeed()) + cr2.Status = status + Expect(k8sClient.Status().Update(ctx, cr2)).Should(Succeed()) + + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: cr2.Name + "-instance-pod", + Namespace: cr2.Namespace, + Labels: map[string]string{ + "postgres-operator.crunchydata.com/cluster": cr2.Name, + "postgres-operator.crunchydata.com/instance": "instance", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "database", + Image: "postgres:16", + }, + }, + }, + } + Expect(k8sClient.Create(ctx, pod)).Should(Succeed()) + + pod.Status = corev1.PodStatus{ + Phase: corev1.PodRunning, + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "database", + ImageID: "postgres:16", + }, + }, + } + Expect(k8sClient.Status().Update(ctx, pod)).Should(Succeed()) + }) + + It("should create patroni version check pod and return errPatroniVersionCheckWait", func() { + reconcilerInstance := reconciler(cr2) + err := reconcilerInstance.reconcilePatroniVersion(ctx, cr2) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("waiting for pod to initialize")) + }) + + It("should have created patroni version check pod with correct configuration", func() { + podName := cr2.Name + "-patroni-version-check" + pod := &corev1.Pod{} + err = k8sClient.Get(ctx, types.NamespacedName{Name: podName, Namespace: cr2.Namespace}, pod) + Expect(err).NotTo(HaveOccurred()) + + Expect(pod.Spec.Containers).To(HaveLen(1)) + Expect(pod.Spec.Containers[0].Name).To(Equal(pNaming.ContainerPatroniVersionCheck)) + Expect(pod.Spec.Containers[0].Image).To(Equal(cr2.Spec.Image)) + Expect(pod.Spec.Containers[0].Command).To(Equal([]string{"bash"})) + Expect(pod.Spec.Containers[0].Args).To(Equal([]string{"-c", "sleep 60"})) + Expect(pod.Spec.Containers[0].Resources).To(Equal(corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + })) + Expect(pod.Spec.Resources).To(Equal(&corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + })) + + uid := int64(1001) + expectedSecurityContext := &corev1.PodSecurityContext{ + RunAsUser: &uid, + } + expectedImagePullSecrets := []corev1.LocalObjectReference{ + {Name: "test-pull-secret"}, + } + expectedAffinity := &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []corev1.PreferredSchedulingTerm{ + { + Weight: int32(1), + }, + }, + }, + } + + Expect(pod.Spec.SecurityContext).To(Equal(expectedSecurityContext)) + Expect(pod.Spec.TerminationGracePeriodSeconds).To(Equal(ptr.To(int64(5)))) + Expect(pod.Spec.ImagePullSecrets).To(Equal(expectedImagePullSecrets)) + Expect(pod.Spec.Affinity).To(Equal(expectedAffinity)) + }) + + It("should preserve existing patroni version in annotation", func() { + updatedCR := &v2.PerconaPGCluster{} + Expect(k8sClient.Get(ctx, crNamespacedName2, updatedCR)).Should(Succeed()) + + Expect(updatedCR.Status.Patroni.Version).To(Equal("3.1.0")) + Expect(updatedCR.Status.PatroniVersion).To(Equal("3.1.0")) + Expect(updatedCR.Annotations[pNaming.AnnotationPatroniVersion]).To(Equal("3.1.0")) + }) + }) +}) diff --git a/percona/naming/prefix.go b/percona/naming/prefix.go index 4d599b7479..73b78f66a3 100644 --- a/percona/naming/prefix.go +++ b/percona/naming/prefix.go @@ -13,10 +13,6 @@ func ToCrunchyAnnotation(annotation string) string { return replacePrefix(annotation, PrefixPerconaPGV2, PrefixCrunchy) } -func ToPerconaAnnotation(annotation string) string { - return replacePrefix(annotation, PrefixCrunchy, PrefixPerconaPGV2) -} - func replacePrefix(s, oldPrefix, newPrefix string) string { s, found := strings.CutPrefix(s, oldPrefix) if found { diff --git a/percona/postgres/common.go b/percona/postgres/common.go index f0a8c05b5a..41026ade48 100644 --- a/percona/postgres/common.go +++ b/percona/postgres/common.go @@ -12,18 +12,19 @@ import ( v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) +const ( + patroniVersion4 = "4.0.0" +) + +// GetPrimaryPod returns the primary pod. +// K8SPG-882 func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGCluster) (*corev1.Pod, error) { podList := &corev1.PodList{} // K8SPG-648: patroni v4.0.0 deprecated "master" role. // We should use "primary" instead role := "primary" - patroniVersion := cr.Status.PatroniVersion - if cr.CompareVersion("2.8.0") >= 0 { - patroniVersion = cr.Status.Patroni.Version - } - - patroniVer, err := gover.NewVersion(patroniVersion) + patroniVer, err := gover.NewVersion(determineVersion(cr)) if err != nil { return nil, errors.Wrap(err, "failed to get patroni version") } @@ -39,7 +40,7 @@ func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGClust }), }) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to list pods") } if len(podList.Items) == 0 { @@ -52,3 +53,10 @@ func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGClust return &podList.Items[0], nil } + +func determineVersion(cr *v2.PerconaPGCluster) string { + if cr.CompareVersion("2.7.0") <= 0 { + return cr.Status.PatroniVersion + } + return patroniVersion4 +} diff --git a/percona/postgres/common_test.go b/percona/postgres/common_test.go new file mode 100644 index 0000000000..8570e9d41a --- /dev/null +++ b/percona/postgres/common_test.go @@ -0,0 +1,380 @@ +package perconaPG + +import ( + "context" + "testing" + + "gotest.tools/v3/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/version" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" +) + +func TestGetPrimaryPod(t *testing.T) { + ctx := context.Background() + + tests := map[string]struct { + cr *v2.PerconaPGCluster + pods []corev1.Pod + expectedError string + expectedPod string + }{ + "patroni 4.1.0 with annotation": { + cr: &v2.PerconaPGCluster{ + Spec: v2.PerconaPGClusterSpec{ + CRVersion: version.Version(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + Annotations: map[string]string{ + pNaming.AnnotationPatroniVersion: "4.1.0", + }, + }, + Status: v2.PerconaPGClusterStatus{ + Patroni: v2.Patroni{ + Version: "4.0.0", + }, + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-1", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "something", + }, + }, + }, + }, + expectedPod: "test-cluster-primary-0", + }, + "patroni 4.0.0 without annotation": { + cr: &v2.PerconaPGCluster{ + Spec: v2.PerconaPGClusterSpec{ + CRVersion: version.Version(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Status: v2.PerconaPGClusterStatus{ + Patroni: v2.Patroni{ + Version: "4.0.0", + }, + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-1", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "something", + }, + }, + }, + }, + expectedPod: "test-cluster-primary-0", + }, + "patroni 3.x with master role": { + cr: &v2.PerconaPGCluster{ + Spec: v2.PerconaPGClusterSpec{ + CRVersion: "2.7.0", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Status: v2.PerconaPGClusterStatus{ + PatroniVersion: "3.0.0", + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-master-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "master", + }, + }, + }, + }, + expectedPod: "test-cluster-master-0", + }, + "patroni version from annotation overrides status for version >= 2.8.0": { + cr: &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + Annotations: map[string]string{ + pNaming.AnnotationPatroniVersion: "4.1.0", + }, + }, + Spec: v2.PerconaPGClusterSpec{ + PostgresVersion: 16, + CRVersion: version.Version(), + }, + Status: v2.PerconaPGClusterStatus{ + PatroniVersion: "3.0.0", + Postgres: v2.PostgresStatus{ + Version: 16, + }, + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + }, + }, + expectedPod: "test-cluster-primary-0", + }, + "patroni version from status used for version < 2.8.0": { + cr: &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + Annotations: map[string]string{ + pNaming.AnnotationPatroniVersion: "4.0.0", + }, + }, + Spec: v2.PerconaPGClusterSpec{ + PostgresVersion: 14, + CRVersion: "2.7.0", + }, + Status: v2.PerconaPGClusterStatus{ + PatroniVersion: "3.0.0", + Postgres: v2.PostgresStatus{ + Version: 14, + }, + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-master-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "master", + }, + }, + }, + }, + expectedPod: "test-cluster-master-0", + }, + "no primary pod found": { + cr: &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + Annotations: map[string]string{ + pNaming.AnnotationPatroniVersion: "4.1.0", + }, + }, + Spec: v2.PerconaPGClusterSpec{ + PostgresVersion: 14, + CRVersion: version.Version(), + }, + }, + pods: []corev1.Pod{}, + expectedError: "no primary pod found", + }, + "multiple primary pods found": { + cr: &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Status: v2.PerconaPGClusterStatus{ + PatroniVersion: "4.0.0", + }, + Spec: v2.PerconaPGClusterSpec{ + CRVersion: version.Version(), + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-1", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + }, + }, + expectedError: "multiple primary pods found", + }, + "invalid patroni version returns the default primary": { + cr: &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Status: v2.PerconaPGClusterStatus{ + PatroniVersion: "invalid-version", + }, + Spec: v2.PerconaPGClusterSpec{ + CRVersion: version.Version(), + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-master-1", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "master", + }, + }, + }, + }, + expectedPod: "test-cluster-primary-0", + }, + "patroni 4.1.0-beta with primary role": { + cr: &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + Annotations: map[string]string{ + pNaming.AnnotationPatroniVersion: "4.1.0-beta.1", + }, + }, + Spec: v2.PerconaPGClusterSpec{ + CRVersion: version.Version(), + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-primary-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + }, + }, + expectedPod: "test-cluster-primary-0", + }, + "patroni 3.9.9 with master role (just before 4.0.0)": { + cr: &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-namespace", + }, + Status: v2.PerconaPGClusterStatus{ + PatroniVersion: "3.9.9", + }, + Spec: v2.PerconaPGClusterSpec{ + CRVersion: "2.7.0", + }, + }, + pods: []corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-master-0", + Namespace: "test-namespace", + Labels: map[string]string{ + "app.kubernetes.io/instance": "test-cluster", + "postgres-operator.crunchydata.com/role": "master", + }, + }, + }, + }, + expectedPod: "test-cluster-master-0", + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + scheme := runtime.NewScheme() + err := corev1.AddToScheme(scheme) + assert.NilError(t, err) + err = v2.AddToScheme(scheme) + assert.NilError(t, err) + + objects := []runtime.Object{tt.cr} + for i := range tt.pods { + objects = append(objects, &tt.pods[i]) + } + + fakeClient := fake.NewClientBuilder(). + WithScheme(scheme). + WithRuntimeObjects(objects...). + Build() + + pod, err := GetPrimaryPod(ctx, fakeClient, tt.cr) + + if tt.expectedError != "" { + assert.ErrorContains(t, err, tt.expectedError) + assert.Assert(t, pod == nil) + } else { + assert.NilError(t, err) + assert.Assert(t, pod != nil) + assert.Equal(t, pod.Name, tt.expectedPod) + } + }) + } +} diff --git a/percona/watcher/wal_test.go b/percona/watcher/wal_test.go index d50375a8ee..f6442391b0 100644 --- a/percona/watcher/wal_test.go +++ b/percona/watcher/wal_test.go @@ -348,7 +348,7 @@ func TestGetLatestCommitTimestamp(t *testing.T) { CRVersion: version.Version(), }, }, - expectedErr: errors.New("failed to get patroni version: Malformed version: error: primary pod not found"), + expectedErr: errors.New("primary pod not found"), }, } for name, tt := range tests { @@ -357,7 +357,7 @@ func TestGetLatestCommitTimestamp(t *testing.T) { _, err := GetLatestCommitTimestamp(ctx, c, nil, tt.cluster, tt.backup) - assert.EqualError(t, err, tt.expectedErr.Error()) + assert.ErrorContains(t, err, tt.expectedErr.Error()) }) } } From 3c6956338260a9838caf1c1ea282ff5019578838 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Mon, 3 Nov 2025 21:49:42 +0200 Subject: [PATCH 200/300] K8SPG-836: Update versions for 2.8.0 release (#1342) * K8SPG-836: Update versions for 2.8.0 release * K8SPG-836: use version for release reviewdog manifest testss --- .github/workflows/reviewdog.yml | 9 ++- config/bundle/kustomization.yaml | 4 +- config/cw-bundle/kustomization.yaml | 4 +- config/manager/cluster/kustomization.yaml | 4 +- config/manager/namespace/kustomization.yaml | 4 +- deploy/bundle.yaml | 2 +- deploy/cr.yaml | 16 ++--- deploy/cw-bundle.yaml | 2 +- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 +-- e2e-tests/release_versions | 69 +++++++++++---------- 12 files changed, 67 insertions(+), 59 deletions(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 971eb5a4a1..921c73146c 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -93,6 +93,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - run: | + - name: check on release branch + if: ${{ contains(github.head_ref, 'release-') || contains(github.base_ref, 'release-') }} + run: | + make generate VERSION="$(cat percona/version/version.txt)" IMAGE_TAG_BASE="percona/percona-postgresql-operator" + git diff --exit-code + - name: check on non release branches + if: ${{ ! (contains(github.head_ref, 'release-') || contains(github.base_ref, 'release-')) }} + run: | make generate VERSION=main git diff --exit-code diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index 90cf89956e..0412fd1ddd 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -6,5 +6,5 @@ resources: - ../manager/namespace images: - name: postgres-operator - newName: docker.io/perconalab/percona-postgresql-operator - newTag: main + newName: docker.io/percona/percona-postgresql-operator + newTag: 2.8.0 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 440d098731..0b3c810eab 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -7,5 +7,5 @@ resources: images: - name: postgres-operator - newName: docker.io/perconalab/percona-postgresql-operator - newTag: main + newName: docker.io/percona/percona-postgresql-operator + newTag: 2.8.0 diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index 6f8f4bf129..940a80d27b 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -8,5 +8,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/perconalab/percona-postgresql-operator - newTag: main + newName: docker.io/percona/percona-postgresql-operator + newTag: 2.8.0 diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index a57ff786e0..1e4cfc0e67 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -9,5 +9,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/perconalab/percona-postgresql-operator - newTag: main + newName: docker.io/percona/percona-postgresql-operator + newTag: 2.8.0 diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index e93e6e85ad..020076242b 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -53964,7 +53964,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/perconalab/percona-postgresql-operator:main + image: docker.io/percona/percona-postgresql-operator:2.8.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index e055bc6f38..ed3064d5d1 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -11,7 +11,7 @@ metadata: spec: crVersion: 2.8.0 # initContainer: -# image: docker.io/perconalab/percona-postgresql-operator:main +# image: docker.io/percona/percona-postgresql-operator:2.8.0 # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres + image: docker.io/percona/percona-distribution-postgresql:17.6-1 imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -188,7 +188,7 @@ spec: # - secretRef: # name: instance-env-secret # initContainer: -# image: docker.io/perconalab/percona-postgresql-operator:main +# image: docker.io/percona/percona-postgresql-operator:2.8.0 # resources: # limits: # cpu: 2.0 @@ -312,7 +312,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 + image: docker.io/percona/percona-pgbouncer:1.24.1-1 # env: # - name: MY_ENV # value: "1000" @@ -409,7 +409,7 @@ spec: pgbackrest: # metadata: # labels: - image: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 + image: docker.io/percona/percona-pgbackrest:2.56.0-1 # env: # - name: MY_ENV # value: "1000" @@ -417,7 +417,7 @@ spec: # - secretRef: # name: repo-host-env-secret # initContainer: -# image: docker.io/perconalab/percona-postgresql-operator:main +# image: docker.io/percona/percona-postgresql-operator:2.8.0 # resources: # limits: # cpu: 2.0 @@ -613,7 +613,7 @@ spec: pmm: enabled: false - image: docker.io/perconalab/pmm-client:dev-latest + image: docker.io/percona/pmm-client:3.4.1 # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -647,7 +647,7 @@ spec: # - basebackup # extensions: -# image: docker.io/perconalab/percona-postgresql-operator:main +# image: docker.io/percona/percona-postgresql-operator:2.8.0 # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 669b9940ec..3fc6cc1c48 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -53962,7 +53962,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/perconalab/percona-postgresql-operator:main + image: docker.io/percona/percona-postgresql-operator:2.8.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 7861413845..1abc72e4c5 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/perconalab/percona-postgresql-operator:main + image: docker.io/percona/percona-postgresql-operator:2.8.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index c6c492333b..7da02aca8d 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/perconalab/percona-postgresql-operator:main + image: docker.io/percona/percona-postgresql-operator:2.8.0 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 59ddf91d3b..2a28427a41 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: docker.io/perconalab/percona-postgresql-operator:main-upgrade + image: docker.io/percona/percona-postgresql-operator:2.8.0-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres - toPgBouncerImage: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 - toPgBackRestImage: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 + toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.6-1 + toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.24.1-1 + toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.56.0-1 diff --git a/e2e-tests/release_versions b/e2e-tests/release_versions index 4e7b46b824..a425622447 100644 --- a/e2e-tests/release_versions +++ b/e2e-tests/release_versions @@ -1,45 +1,46 @@ # Images versions -IMAGE_OPERATOR=percona/percona-postgresql-operator:2.7.0 +IMAGE_OPERATOR=percona/percona-postgresql-operator:2.8.0 -IMAGE_POSTGRESQL17=percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres -IMAGE_PGBOUNCER17=percona/percona-pgbouncer:1.24.1 -IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.7.0-ppg17.5.2-postgres-gis3.3.8 -IMAGE_BACKREST17=percona/percona-pgbackrest:2.55.0 +IMAGE_POSTGRESQL17=percona/percona-distribution-postgresql:17.6-1 +IMAGE_PGBOUNCER17=percona/percona-pgbouncer:1.24.1-1 +IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.8.0-ppg17.6-postgres-gis3.3.8 +IMAGE_BACKREST17=percona/percona-pgbackrest:2.56.0-1 -IMAGE_POSTGRESQL16=percona/percona-postgresql-operator:2.7.0-ppg16.9-postgres -IMAGE_PGBOUNCER16=percona/percona-pgbouncer:1.24.1 -IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.7.0-ppg16.9-postgres-gis3.3.8 -IMAGE_BACKREST16=percona/percona-pgbackrest:2.55.0 +IMAGE_POSTGRESQL16=percona/percona-distribution-postgresql:16.10-1 +IMAGE_PGBOUNCER16=percona/percona-pgbouncer:1.24.1-1 +IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.8.0-ppg16.10-postgres-gis3.3.8 +IMAGE_BACKREST16=percona/percona-pgbackrest:2.56.0-1 -IMAGE_POSTGRESQL15=percona/percona-postgresql-operator:2.7.0-ppg15.13-postgres -IMAGE_PGBOUNCER15=percona/percona-pgbouncer:1.24.1 -IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.7.0-ppg15.13-postgres-gis3.3.8 -IMAGE_BACKREST15=percona/percona-pgbackrest:2.55.0 +IMAGE_POSTGRESQL15=percona/percona-distribution-postgresql:15.14-1 +IMAGE_PGBOUNCER15=percona/percona-pgbouncer:1.24.1-1 +IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.8.0-ppg15.14-postgres-gis3.3.8 +IMAGE_BACKREST15=percona/percona-pgbackrest:2.56.0-1 -IMAGE_POSTGRESQL14=percona/percona-postgresql-operator:2.7.0-ppg14.18-postgres -IMAGE_PGBOUNCER14=percona/percona-pgbouncer:1.24.1 -IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.7.0-ppg14.18-postgres-gis3.3.8 -IMAGE_BACKREST14=percona/percona-pgbackrest:2.55.0 +IMAGE_POSTGRESQL14=percona/percona-distribution-postgresql:14.19-1 +IMAGE_PGBOUNCER14=percona/percona-pgbouncer:1.24.1-1 +IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.8.0-ppg14.19-postgres-gis3.3.8 +IMAGE_BACKREST14=percona/percona-pgbackrest:2.56.0-1 -IMAGE_POSTGRESQL13=percona/percona-postgresql-operator:2.7.0-ppg13.21-postgres -IMAGE_PGBOUNCER13=percona/percona-pgbouncer:1.24.1 -IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.7.0-ppg13.21-postgres-gis3.3.8 -IMAGE_BACKREST13=percona/percona-pgbackrest:2.55.0 +IMAGE_POSTGRESQL13=percona/percona-distribution-postgresql:13.22-1 +IMAGE_PGBOUNCER13=percona/percona-pgbouncer:1.24.1-1 +IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.8.0-ppg13.22-postgres-gis3.3.8 +IMAGE_BACKREST13=percona/percona-pgbackrest:2.56.0-1 -IMAGE_UPGRADE=percona/percona-postgresql-operator:2.7.0-upgrade +IMAGE_UPGRADE=percona/percona-postgresql-operator:2.8.0-upgrade -IMAGE_PMM_CLIENT=percona/pmm-client:2.44.1 +IMAGE_PMM_CLIENT=percona/pmm-client:2.44.1-1 IMAGE_PMM_SERVER=percona/pmm-server:2.44.1 -IMAGE_PMM3_CLIENT=percona/pmm-client:3.3.0 -IMAGE_PMM3_SERVER=percona/pmm-server:3.3.0 +IMAGE_PMM3_CLIENT=percona/pmm-client:3.4.1 +IMAGE_PMM3_SERVER=percona/pmm-server:3.4.1 # Supported k8s versions -GKE_MIN=1.30 -GKE_MAX=1.32 -EKS_MIN=1.30 -EKS_MAX=1.33 -AKS_MIN=1.30 -AKS_MAX=1.32 -OPENSHIFT_MIN=4.15.53 -OPENSHIFT_MAX=4.19.2 -MINIKUBE_MAX=1.33.1 \ No newline at end of file +GKE_MIN=1.31 +GKE_MAX=1.33 +EKS_MIN=1.31 +EKS_MAX=1.34 +AKS_MIN=1.32 +AKS_MAX=1.34 +OPENSHIFT_MIN=4.16.51 +OPENSHIFT_MAX=4.20.2 +# MINIKUBE_MAX = k8s version in MINIKUBE +MINIKUBE_MAX=1.34.0 \ No newline at end of file From fed0fc6db4be6f47ef7dac91623fc5a69187adf0 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Tue, 4 Nov 2025 00:01:03 +0200 Subject: [PATCH 201/300] K8SPG-836: bump cert manager version (#1343) --- e2e-tests/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 08c65e8760..983e345d28 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -2,7 +2,7 @@ # set root repo relatively to a test dir ROOT_REPO=${ROOT_REPO:-$(realpath ../../..)} -CERT_MANAGER_VER="1.18.2" +CERT_MANAGER_VER="1.19.1" test_name=$(basename "$(pwd)") source "${ROOT_REPO}/e2e-tests/vars.sh" From b68ed2af7c828358f1cd914ed29666d9ff095aa1 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 6 Nov 2025 18:49:29 +0100 Subject: [PATCH 202/300] K8SPG-833_fix_test add stability (#1344) * K8SPG-833_fix_test add stability * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * fix --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- e2e-tests/functions | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 08c65e8760..a2cd3b3651 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -1036,16 +1036,22 @@ get_desired_replicas() { kubectl get statefulset "$1" -n "$NAMESPACE" -o jsonpath='{.spec.replicas}' } +get_ready_replicas() { + kubectl get sts "$1" -n "$NAMESPACE" -o jsonpath='{.status.readyReplicas}' +} + wait_sts_rollout() { local sts=$1 + local ready_replicas=$(get_ready_replicas $sts) local updated_replicas=$(get_updated_replicas $sts) local desired_replicas=$(get_desired_replicas $sts) + echo "ready_replicas $ready_replicas desired_replicas $desired_replicas" - until [[ $updated_replicas -eq $desired_replicas ]]; do - updated_replicas=$(get_updated_replicas $sts) + until [[ $ready_replicas -eq $desired_replicas && $updated_replicas -eq $desired_replicas ]]; do + ready_replicas=$(get_ready_replicas $sts) desired_replicas=$(get_desired_replicas $sts) - - echo "Waiting for sts/$sts to update... $updated_replicas/$desired_replicas pods updated." + updated_replicas=$(get_updated_replicas $sts) + echo "Waiting for sts/$sts to update... $ready_replicas/$updated_replicas/$desired_replicas pods updated." sleep 10 done } From 36285879c38a651b729559d8d6e4c3695453eaf1 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Thu, 6 Nov 2025 19:50:52 +0200 Subject: [PATCH 203/300] K8SPG-836: increase sleep for telemetry transfer tests --- .../tests/telemetry-transfer/04-verify-transferred-pmm.yaml | 2 +- .../tests/telemetry-transfer/05-verify-transferred-helm-cr.yaml | 2 +- .../telemetry-transfer/06-verify-transferred-sidecars.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e-tests/tests/telemetry-transfer/04-verify-transferred-pmm.yaml b/e2e-tests/tests/telemetry-transfer/04-verify-transferred-pmm.yaml index b87ae394ec..75f10545b0 100644 --- a/e2e-tests/tests/telemetry-transfer/04-verify-transferred-pmm.yaml +++ b/e2e-tests/tests/telemetry-transfer/04-verify-transferred-pmm.yaml @@ -9,7 +9,7 @@ commands: source ../../functions kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=merge -p '{"spec":{"pmm":{"enabled":true}}}' - sleep 5 + sleep 7 CR_ID=$(kubectl -n ${NAMESPACE} get perconapgcluster/${test_name} --template='{{.metadata.uid}}') TRANSFERRED_KEYS=$(kubectl -n ${NAMESPACE} logs -l run=version-service| grep ${CR_ID} | tail -n1 | grep -Eo '\{.*\}$' | jq '."grpc.request.content".msg | keys') kubectl create configmap -n "${NAMESPACE}" 04-verify-tramsferred-pmm --from-literal=keys="${TRANSFERRED_KEYS}" \ No newline at end of file diff --git a/e2e-tests/tests/telemetry-transfer/05-verify-transferred-helm-cr.yaml b/e2e-tests/tests/telemetry-transfer/05-verify-transferred-helm-cr.yaml index 859984246c..736809a7da 100644 --- a/e2e-tests/tests/telemetry-transfer/05-verify-transferred-helm-cr.yaml +++ b/e2e-tests/tests/telemetry-transfer/05-verify-transferred-helm-cr.yaml @@ -9,7 +9,7 @@ commands: source ../../functions kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=merge -p '{"metadata":{"labels":{"helm.sh/chart":"fake-chart-to-verify-telemetry-transfer"}}}' - sleep 5 + sleep 7 CR_ID=$(kubectl -n ${NAMESPACE} get perconapgcluster/${test_name} --template='{{.metadata.uid}}') TRANSFERRED_KEYS=$(kubectl -n ${NAMESPACE} logs -l run=version-service| grep ${CR_ID} | tail -n1 | grep -Eo '\{.*\}$' | jq '."grpc.request.content".msg | keys') kubectl create configmap -n "${NAMESPACE}" 05-verify-tramsferred-helm-cr --from-literal=keys="${TRANSFERRED_KEYS}" \ No newline at end of file diff --git a/e2e-tests/tests/telemetry-transfer/06-verify-transferred-sidecars.yaml b/e2e-tests/tests/telemetry-transfer/06-verify-transferred-sidecars.yaml index e75fef4553..8aeec9f576 100644 --- a/e2e-tests/tests/telemetry-transfer/06-verify-transferred-sidecars.yaml +++ b/e2e-tests/tests/telemetry-transfer/06-verify-transferred-sidecars.yaml @@ -9,7 +9,7 @@ commands: source ../../functions kubectl -n ${NAMESPACE} patch perconapgcluster/${test_name} --type=json -p '[{"op":"add","path":"/spec/instances/0/sidecars","value":[{"name":"testcontainer","image":"busybox","command":["sleep","infinity"]}]}]' - sleep 5 + sleep 7 CR_ID=$(kubectl -n ${NAMESPACE} get perconapgcluster/${test_name} --template='{{.metadata.uid}}') TRANSFERRED_KEYS=$(kubectl -n ${NAMESPACE} logs -l run=version-service| grep ${CR_ID} | tail -n1 | grep -Eo '\{.*\}$' | jq '."grpc.request.content".msg | keys') kubectl create configmap -n "${NAMESPACE}" 06-verify-tramsferred-sidecars --from-literal=keys="${TRANSFERRED_KEYS}" \ No newline at end of file From 6fb3c959d9ba0279e1ff69d4a1b0cf69d93d4bb0 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Thu, 6 Nov 2025 18:49:29 +0100 Subject: [PATCH 204/300] K8SPG-833_fix_test add stability (#1344) * K8SPG-833_fix_test add stability * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * fix --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- e2e-tests/functions | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 983e345d28..e69256717e 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -1036,16 +1036,22 @@ get_desired_replicas() { kubectl get statefulset "$1" -n "$NAMESPACE" -o jsonpath='{.spec.replicas}' } +get_ready_replicas() { + kubectl get sts "$1" -n "$NAMESPACE" -o jsonpath='{.status.readyReplicas}' +} + wait_sts_rollout() { local sts=$1 + local ready_replicas=$(get_ready_replicas $sts) local updated_replicas=$(get_updated_replicas $sts) local desired_replicas=$(get_desired_replicas $sts) + echo "ready_replicas $ready_replicas desired_replicas $desired_replicas" - until [[ $updated_replicas -eq $desired_replicas ]]; do - updated_replicas=$(get_updated_replicas $sts) + until [[ $ready_replicas -eq $desired_replicas && $updated_replicas -eq $desired_replicas ]]; do + ready_replicas=$(get_ready_replicas $sts) desired_replicas=$(get_desired_replicas $sts) - - echo "Waiting for sts/$sts to update... $updated_replicas/$desired_replicas pods updated." + updated_replicas=$(get_updated_replicas $sts) + echo "Waiting for sts/$sts to update... $ready_replicas/$updated_replicas/$desired_replicas pods updated." sleep 10 done } From b881c3c030a703ae80a72605a0949c94e853024d Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Thu, 6 Nov 2025 21:46:01 +0200 Subject: [PATCH 205/300] Increase timout for telemetry-transfer --- e2e-tests/tests/telemetry-transfer/02-assert.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/telemetry-transfer/02-assert.yaml b/e2e-tests/tests/telemetry-transfer/02-assert.yaml index 010577755c..8359a47764 100644 --- a/e2e-tests/tests/telemetry-transfer/02-assert.yaml +++ b/e2e-tests/tests/telemetry-transfer/02-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 120 +timeout: 240 --- kind: StatefulSet apiVersion: apps/v1 From d1c1bc0bdf03b33c71fcd3cc8a3c3200ed8ded4b Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Fri, 7 Nov 2025 21:52:52 +0200 Subject: [PATCH 206/300] K8SPG-836: custom-envs test - insrease timeout for cluster start --- e2e-tests/tests/custom-envs/01-assert.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/custom-envs/01-assert.yaml b/e2e-tests/tests/custom-envs/01-assert.yaml index 9f767a78f3..cc0e97651f 100644 --- a/e2e-tests/tests/custom-envs/01-assert.yaml +++ b/e2e-tests/tests/custom-envs/01-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 120 +timeout: 240 --- kind: StatefulSet apiVersion: apps/v1 From 15c51a27bf0b09d25a295093fd7d89b4d7feea5b Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 12 Nov 2025 17:04:41 +0200 Subject: [PATCH 207/300] K8SPG-893 configure LC_ALL and LANG for database containers (#1350) * K8SPG-893 configure LC_ALL and LANG for database containers * copy env from database to upgrade container * fix tests * guard with version 2.8 * fix * set version to latest for unit test pod allow volume grow * add only the needed env vars instead of the whole database env * fix unit test --- internal/controller/pgupgrade/jobs.go | 14 ++++++++++++++ internal/controller/pgupgrade/jobs_test.go | 5 +++++ internal/postgres/config.go | 15 +++++++++++++++ internal/postgres/reconcile_test.go | 18 +++++++++++++++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/internal/controller/pgupgrade/jobs.go b/internal/controller/pgupgrade/jobs.go index 9ce675f89b..3d74379d10 100644 --- a/internal/controller/pgupgrade/jobs.go +++ b/internal/controller/pgupgrade/jobs.go @@ -203,6 +203,20 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( SecurityContext: database.SecurityContext, VolumeMounts: volumeMounts, // K8SPG-254 + // K8SPG-893 + Env: []corev1.EnvVar{ + // Critical for major upgrades to avoid lc_collate mismatches. + // - https://www.postgresql.org/docs/current/locale.html + { + Name: "LC_ALL", + Value: "en_US.utf-8", + }, + { + Name: "LANG", + Value: "en_US.utf-8", + }, + }, + // Use our upgrade command and the specified image and resources. Command: upgradeCommand( upgrade.Spec.FromPostgresVersion, diff --git a/internal/controller/pgupgrade/jobs_test.go b/internal/controller/pgupgrade/jobs_test.go index 79075b1c24..992503b7ff 100644 --- a/internal/controller/pgupgrade/jobs_test.go +++ b/internal/controller/pgupgrade/jobs_test.go @@ -203,6 +203,11 @@ spec: - upgrade - "19" - "25" + env: + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 image: img4 name: database resources: diff --git a/internal/postgres/config.go b/internal/postgres/config.go index 1ac7b38a86..feda6d8aa1 100644 --- a/internal/postgres/config.go +++ b/internal/postgres/config.go @@ -164,6 +164,21 @@ func Environment(cluster *v1beta1.PostgresCluster) []corev1.EnvVar { }) } + if cluster.CompareVersion("2.8.0") >= 0 { + env = append(env, []corev1.EnvVar{ + // Critical for major upgrades to avoid lc_collate mismatches. + // - https://www.postgresql.org/docs/current/locale.html + { + Name: "LC_ALL", + Value: "en_US.utf-8", + }, + { + Name: "LANG", + Value: "en_US.utf-8", + }, + }...) + } + return env } diff --git a/internal/postgres/reconcile_test.go b/internal/postgres/reconcile_test.go index 17da5bf3ff..1a3f0dba95 100644 --- a/internal/postgres/reconcile_test.go +++ b/internal/postgres/reconcile_test.go @@ -138,6 +138,10 @@ containers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: database ports: @@ -289,6 +293,10 @@ initContainers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: postgres-startup resources: @@ -713,7 +721,7 @@ func TestInstancePodAllowVolumeGrow(t *testing.T) { cluster.Spec.ImagePullPolicy = corev1.PullAlways cluster.Spec.PostgresVersion = 11 cluster.SetLabels(map[string]string{ - naming.LabelVersion: "2.7.0", + naming.LabelVersion: version.Version(), }) dataVolume := new(corev1.PersistentVolumeClaim) @@ -781,6 +789,10 @@ containers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: database ports: @@ -946,6 +958,10 @@ initContainers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: postgres-startup resources: From 8290a4054887176ca68c0d82745b067428c33970 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 12 Nov 2025 20:38:50 +0200 Subject: [PATCH 208/300] K8SPG-894 upgrade job using the init container from primary sts (#1351) * K8SPG-894 upgrade job using the init container from primary sts * update unit test * configure custom container for the upgrade spec and ensure that everything is considered * change order of init containers * small refactor --- internal/controller/pgupgrade/jobs.go | 18 ++++++++++++++++-- internal/controller/pgupgrade/jobs_test.go | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/internal/controller/pgupgrade/jobs.go b/internal/controller/pgupgrade/jobs.go index 3d74379d10..93b2bad34d 100644 --- a/internal/controller/pgupgrade/jobs.go +++ b/internal/controller/pgupgrade/jobs.go @@ -189,8 +189,22 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( // Replace all containers with one that does the upgrade. job.Spec.Template.Spec.EphemeralContainers = nil - // K8SPG-254: Major upgrade support - job.Spec.Template.Spec.InitContainers = upgrade.Spec.InitContainers + // K8SPG-894: Ensure database init container is included for required scripts + var initContainers []corev1.Container + + dbInitContainerName := ContainerDatabase + "-init" + for _, container := range startup.Spec.Template.Spec.InitContainers { + if container.Name == dbInitContainerName { + initContainers = append(initContainers, container) + break + } + } + + if len(upgrade.Spec.InitContainers) > 0 { + initContainers = append(initContainers, upgrade.Spec.InitContainers...) + } + + job.Spec.Template.Spec.InitContainers = initContainers volumeMounts := database.VolumeMounts volumeMounts = append(volumeMounts, upgrade.Spec.VolumeMounts...) diff --git a/internal/controller/pgupgrade/jobs_test.go b/internal/controller/pgupgrade/jobs_test.go index 992503b7ff..7f1e5a32b6 100644 --- a/internal/controller/pgupgrade/jobs_test.go +++ b/internal/controller/pgupgrade/jobs_test.go @@ -110,9 +110,19 @@ func TestGenerateUpgradeJob(t *testing.T) { upgrade.Spec.Resources.Requests = corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("3.14"), } + upgrade.Spec.InitContainers = []corev1.Container{ + { + Name: "upgrade-init-container", + }, + } startup := &appsv1.StatefulSet{} startup.Spec.Template.Spec = corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: ContainerDatabase + "-init", + }, + }, Containers: []corev1.Container{{ Name: ContainerDatabase, @@ -218,6 +228,11 @@ spec: volumeMounts: - mountPath: /mnt/some/such name: vm1 + initContainers: + - name: database-init + resources: {} + - name: upgrade-init-container + resources: {} restartPolicy: Never volumes: - hostPath: From 5a2ced46f64cc2630e5db5972ae4a00e468cae09 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Wed, 12 Nov 2025 20:46:42 +0200 Subject: [PATCH 209/300] K8SPG-894: bring back major-upgrade test but remove restores from it (#1352) * Restore ajor upgrade tests * Remove restore from major upgrade to make test more stable * K8SPG-894: bring back major upgrade tests * Fix repos and use sequential --- e2e-tests/functions | 6 +- e2e-tests/run-release.csv | 1 + .../major-upgrade/01-create-cluster.yaml | 8 +-- .../{20-13-to-14.yaml => 04-13-to-14.yaml} | 0 .../{30-assert.yaml => 04-assert.yaml} | 4 +- .../{46-assert.yaml => 05-assert.yaml} | 2 +- ...1-change-repo.yaml => 05-change-repo.yaml} | 0 .../{22-assert.yaml => 06-assert.yaml} | 4 +- ...{22-run-backup.yaml => 06-run-backup.yaml} | 2 +- .../{24-assert.yaml => 07-assert.yaml} | 0 ...primary.yaml => 07-read-from-primary.yaml} | 0 .../{30-14-to-15.yaml => 08-14-to-15.yaml} | 0 .../{20-assert.yaml => 08-assert.yaml} | 2 +- .../{21-assert.yaml => 09-assert.yaml} | 0 ...1-change-repo.yaml => 09-change-repo.yaml} | 0 .../tests/major-upgrade/10-12-to-13.yaml | 24 -------- e2e-tests/tests/major-upgrade/10-assert.yaml | 45 ++++++--------- ...{32-run-backup.yaml => 10-run-backup.yaml} | 2 +- e2e-tests/tests/major-upgrade/11-assert.yaml | 23 ++------ ...primary.yaml => 11-read-from-primary.yaml} | 0 .../{40-15-to-16.yaml => 12-15-to-16.yaml} | 0 e2e-tests/tests/major-upgrade/12-assert.yaml | 45 +++++++++------ .../tests/major-upgrade/12-run-backup.yaml | 9 --- e2e-tests/tests/major-upgrade/13-assert.yaml | 57 +++++-------------- ...1-change-repo.yaml => 13-change-repo.yaml} | 0 .../tests/major-upgrade/13-run-restore.yaml | 7 --- e2e-tests/tests/major-upgrade/14-assert.yaml | 33 +++++++++-- .../major-upgrade/14-read-from-primary.yaml | 12 ---- ...{42-run-backup.yaml => 14-run-backup.yaml} | 2 +- .../{44-assert.yaml => 15-assert.yaml} | 2 +- ...primary.yaml => 15-read-from-primary.yaml} | 2 +- .../{45-16-to-17.yaml => 16-16-to-17.yaml} | 0 .../{45-assert.yaml => 16-assert.yaml} | 0 .../{31-assert.yaml => 17-assert.yaml} | 0 .../{32-assert.yaml => 18-assert.yaml} | 4 +- ...{47-run-backup.yaml => 18-run-backup.yaml} | 2 +- .../{34-assert.yaml => 19-assert.yaml} | 2 +- ...primary.yaml => 19-read-from-primary.yaml} | 2 +- e2e-tests/tests/major-upgrade/23-assert.yaml | 52 ----------------- .../tests/major-upgrade/23-run-restore.yaml | 7 --- e2e-tests/tests/major-upgrade/33-assert.yaml | 52 ----------------- .../tests/major-upgrade/33-run-restore.yaml | 8 --- e2e-tests/tests/major-upgrade/40-assert.yaml | 42 -------------- e2e-tests/tests/major-upgrade/41-assert.yaml | 21 ------- .../tests/major-upgrade/41-change-repo.yaml | 12 ---- e2e-tests/tests/major-upgrade/42-assert.yaml | 31 ---------- e2e-tests/tests/major-upgrade/43-assert.yaml | 52 ----------------- .../tests/major-upgrade/43-run-restore.yaml | 8 --- e2e-tests/tests/major-upgrade/47-assert.yaml | 31 ---------- e2e-tests/tests/major-upgrade/48-assert.yaml | 10 ---- .../tests/major-upgrade/48-run-restore.yaml | 8 --- 51 files changed, 117 insertions(+), 519 deletions(-) rename e2e-tests/tests/major-upgrade/{20-13-to-14.yaml => 04-13-to-14.yaml} (100%) rename e2e-tests/tests/major-upgrade/{30-assert.yaml => 04-assert.yaml} (90%) rename e2e-tests/tests/major-upgrade/{46-assert.yaml => 05-assert.yaml} (96%) rename e2e-tests/tests/major-upgrade/{11-change-repo.yaml => 05-change-repo.yaml} (100%) rename e2e-tests/tests/major-upgrade/{22-assert.yaml => 06-assert.yaml} (88%) rename e2e-tests/tests/major-upgrade/{22-run-backup.yaml => 06-run-backup.yaml} (89%) rename e2e-tests/tests/major-upgrade/{24-assert.yaml => 07-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{24-read-from-primary.yaml => 07-read-from-primary.yaml} (100%) rename e2e-tests/tests/major-upgrade/{30-14-to-15.yaml => 08-14-to-15.yaml} (100%) rename e2e-tests/tests/major-upgrade/{20-assert.yaml => 08-assert.yaml} (97%) rename e2e-tests/tests/major-upgrade/{21-assert.yaml => 09-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{21-change-repo.yaml => 09-change-repo.yaml} (100%) delete mode 100644 e2e-tests/tests/major-upgrade/10-12-to-13.yaml rename e2e-tests/tests/major-upgrade/{32-run-backup.yaml => 10-run-backup.yaml} (89%) rename e2e-tests/tests/major-upgrade/{44-read-from-primary.yaml => 11-read-from-primary.yaml} (100%) rename e2e-tests/tests/major-upgrade/{40-15-to-16.yaml => 12-15-to-16.yaml} (100%) delete mode 100644 e2e-tests/tests/major-upgrade/12-run-backup.yaml rename e2e-tests/tests/major-upgrade/{31-change-repo.yaml => 13-change-repo.yaml} (100%) delete mode 100644 e2e-tests/tests/major-upgrade/13-run-restore.yaml delete mode 100644 e2e-tests/tests/major-upgrade/14-read-from-primary.yaml rename e2e-tests/tests/major-upgrade/{42-run-backup.yaml => 14-run-backup.yaml} (89%) rename e2e-tests/tests/major-upgrade/{44-assert.yaml => 15-assert.yaml} (81%) rename e2e-tests/tests/major-upgrade/{34-read-from-primary.yaml => 15-read-from-primary.yaml} (85%) rename e2e-tests/tests/major-upgrade/{45-16-to-17.yaml => 16-16-to-17.yaml} (100%) rename e2e-tests/tests/major-upgrade/{45-assert.yaml => 16-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{31-assert.yaml => 17-assert.yaml} (100%) rename e2e-tests/tests/major-upgrade/{32-assert.yaml => 18-assert.yaml} (93%) rename e2e-tests/tests/major-upgrade/{47-run-backup.yaml => 18-run-backup.yaml} (89%) rename e2e-tests/tests/major-upgrade/{34-assert.yaml => 19-assert.yaml} (81%) rename e2e-tests/tests/major-upgrade/{49-read-from-primary.yaml => 19-read-from-primary.yaml} (85%) delete mode 100644 e2e-tests/tests/major-upgrade/23-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/23-run-restore.yaml delete mode 100644 e2e-tests/tests/major-upgrade/33-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/33-run-restore.yaml delete mode 100644 e2e-tests/tests/major-upgrade/40-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/41-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/41-change-repo.yaml delete mode 100644 e2e-tests/tests/major-upgrade/42-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/43-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/43-run-restore.yaml delete mode 100644 e2e-tests/tests/major-upgrade/47-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/48-assert.yaml delete mode 100644 e2e-tests/tests/major-upgrade/48-run-restore.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index e69256717e..ecdb008d13 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -1114,7 +1114,11 @@ get_container_image() { operatorVersion=main fi - echo "${IMAGE_BASE}:${operatorVersion}-ppg${pgVersion}-${component}" + if [[ $component == 'pgbouncer' || $component == 'pgbackrest' ]]; then + echo "${IMAGE_BASE}:${operatorVersion}-${component}${pgVersion}" + else + echo "${IMAGE_BASE}:${operatorVersion}-ppg${pgVersion}-${component}" + fi } get_postgresql_logs() { diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 358ce44987..5a53e2617b 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -6,6 +6,7 @@ database-init-sql demand-backup finalizers init-deploy +major-upgrade monitoring monitoring-pmm3 one-pod diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml index 729fbcc51f..ad23c41e3d 100644 --- a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml +++ b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml @@ -10,11 +10,11 @@ commands: get_cr \ | yq eval ' - .spec.postgresVersion = 12 | - .spec.image = "perconalab/percona-postgresql-operator:main-ppg12-postgres" | + .spec.postgresVersion = 13 | + .spec.image = "perconalab/percona-postgresql-operator:main-ppg13-postgres" | .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | - .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-ppg12-pgbouncer" | - .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-ppg12-pgbackrest" | + .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-pgbouncer13" | + .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-pgbackrest13" | .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.1"}]' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade/20-13-to-14.yaml b/e2e-tests/tests/major-upgrade/04-13-to-14.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/20-13-to-14.yaml rename to e2e-tests/tests/major-upgrade/04-13-to-14.yaml diff --git a/e2e-tests/tests/major-upgrade/30-assert.yaml b/e2e-tests/tests/major-upgrade/04-assert.yaml similarity index 90% rename from e2e-tests/tests/major-upgrade/30-assert.yaml rename to e2e-tests/tests/major-upgrade/04-assert.yaml index b871b4faf8..23d3a30f61 100644 --- a/e2e-tests/tests/major-upgrade/30-assert.yaml +++ b/e2e-tests/tests/major-upgrade/04-assert.yaml @@ -11,7 +11,7 @@ kind: PerconaPGCluster metadata: name: major-upgrade spec: - postgresVersion: 15 + postgresVersion: 14 status: pgbouncer: ready: 3 @@ -32,7 +32,7 @@ metadata: postgres-operator.crunchydata.com/cluster: major-upgrade postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo3 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/46-assert.yaml b/e2e-tests/tests/major-upgrade/05-assert.yaml similarity index 96% rename from e2e-tests/tests/major-upgrade/46-assert.yaml rename to e2e-tests/tests/major-upgrade/05-assert.yaml index 1b95780c8f..47ccba03b5 100644 --- a/e2e-tests/tests/major-upgrade/46-assert.yaml +++ b/e2e-tests/tests/major-upgrade/05-assert.yaml @@ -16,6 +16,6 @@ status: pgbackrest: repos: - bound: true - name: repo1 + name: repo2 replicaCreateBackupComplete: true stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/11-change-repo.yaml b/e2e-tests/tests/major-upgrade/05-change-repo.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/11-change-repo.yaml rename to e2e-tests/tests/major-upgrade/05-change-repo.yaml diff --git a/e2e-tests/tests/major-upgrade/22-assert.yaml b/e2e-tests/tests/major-upgrade/06-assert.yaml similarity index 88% rename from e2e-tests/tests/major-upgrade/22-assert.yaml rename to e2e-tests/tests/major-upgrade/06-assert.yaml index 7a2f6c1c0f..605465e35a 100644 --- a/e2e-tests/tests/major-upgrade/22-assert.yaml +++ b/e2e-tests/tests/major-upgrade/06-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-13-to-14 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo3 + postgres-operator.crunchydata.com/pgbackrest-repo: repo2 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -24,7 +24,7 @@ metadata: name: backup-after-13-to-14 spec: pgCluster: major-upgrade - repoName: repo3 + repoName: repo2 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/22-run-backup.yaml b/e2e-tests/tests/major-upgrade/06-run-backup.yaml similarity index 89% rename from e2e-tests/tests/major-upgrade/22-run-backup.yaml rename to e2e-tests/tests/major-upgrade/06-run-backup.yaml index a7a1050c53..aaf7d5a7c4 100644 --- a/e2e-tests/tests/major-upgrade/22-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade/06-run-backup.yaml @@ -4,6 +4,6 @@ metadata: name: backup-after-13-to-14 spec: pgCluster: major-upgrade - repoName: repo3 + repoName: repo2 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/24-assert.yaml b/e2e-tests/tests/major-upgrade/07-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/24-assert.yaml rename to e2e-tests/tests/major-upgrade/07-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/24-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/07-read-from-primary.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/24-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/07-read-from-primary.yaml diff --git a/e2e-tests/tests/major-upgrade/30-14-to-15.yaml b/e2e-tests/tests/major-upgrade/08-14-to-15.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/30-14-to-15.yaml rename to e2e-tests/tests/major-upgrade/08-14-to-15.yaml diff --git a/e2e-tests/tests/major-upgrade/20-assert.yaml b/e2e-tests/tests/major-upgrade/08-assert.yaml similarity index 97% rename from e2e-tests/tests/major-upgrade/20-assert.yaml rename to e2e-tests/tests/major-upgrade/08-assert.yaml index c506a745f5..c00e35e2ae 100644 --- a/e2e-tests/tests/major-upgrade/20-assert.yaml +++ b/e2e-tests/tests/major-upgrade/08-assert.yaml @@ -11,7 +11,7 @@ kind: PerconaPGCluster metadata: name: major-upgrade spec: - postgresVersion: 14 + postgresVersion: 15 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/major-upgrade/21-assert.yaml b/e2e-tests/tests/major-upgrade/09-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/21-assert.yaml rename to e2e-tests/tests/major-upgrade/09-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/21-change-repo.yaml b/e2e-tests/tests/major-upgrade/09-change-repo.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/21-change-repo.yaml rename to e2e-tests/tests/major-upgrade/09-change-repo.yaml diff --git a/e2e-tests/tests/major-upgrade/10-12-to-13.yaml b/e2e-tests/tests/major-upgrade/10-12-to-13.yaml deleted file mode 100644 index 96a7fe9207..0000000000 --- a/e2e-tests/tests/major-upgrade/10-12-to-13.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - kubectl apply -n ${NAMESPACE} -f - <<-EOF - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGUpgrade - metadata: - name: 12-to-13 - spec: - postgresClusterName: major-upgrade - image: ${IMAGE_UPGRADE} - fromPostgresVersion: 12 - toPostgresVersion: 13 - toPostgresImage: $(get_container_image "postgres" 13) - toPgBouncerImage: $(get_container_image "pgbouncer" 13) - toPgBackRestImage: $(get_container_image "pgbackrest" 13) - EOF - diff --git a/e2e-tests/tests/major-upgrade/10-assert.yaml b/e2e-tests/tests/major-upgrade/10-assert.yaml index ae8dcb18f8..4a603ba7e9 100644 --- a/e2e-tests/tests/major-upgrade/10-assert.yaml +++ b/e2e-tests/tests/major-upgrade/10-assert.yaml @@ -1,38 +1,15 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 360 -commands: -- script: |- - kubectl -n ${NAMESPACE} get pg,pod,job - sleep 5 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: major-upgrade -spec: - postgresVersion: 13 -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready +timeout: 660 --- kind: Job apiVersion: batch/v1 metadata: + annotations: + postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-14-to-15 labels: - postgres-operator.crunchydata.com/cluster: major-upgrade - postgres-operator.crunchydata.com/pgbackrest: '' - postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + postgres-operator.crunchydata.com/pgbackrest-backup: manual + postgres-operator.crunchydata.com/pgbackrest-repo: repo3 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -40,3 +17,15 @@ metadata: blockOwnerDeletion: true status: succeeded: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGBackup +metadata: + name: backup-after-14-to-15 +spec: + pgCluster: major-upgrade + repoName: repo3 + options: + - --type=full +status: + state: Succeeded diff --git a/e2e-tests/tests/major-upgrade/32-run-backup.yaml b/e2e-tests/tests/major-upgrade/10-run-backup.yaml similarity index 89% rename from e2e-tests/tests/major-upgrade/32-run-backup.yaml rename to e2e-tests/tests/major-upgrade/10-run-backup.yaml index 792209c20c..047e0b5571 100644 --- a/e2e-tests/tests/major-upgrade/32-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade/10-run-backup.yaml @@ -4,6 +4,6 @@ metadata: name: backup-after-14-to-15 spec: pgCluster: major-upgrade - repoName: repo4 + repoName: repo3 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/11-assert.yaml b/e2e-tests/tests/major-upgrade/11-assert.yaml index 47ccba03b5..95d57c293f 100644 --- a/e2e-tests/tests/major-upgrade/11-assert.yaml +++ b/e2e-tests/tests/major-upgrade/11-assert.yaml @@ -1,21 +1,10 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - +timeout: 30 --- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster +kind: ConfigMap +apiVersion: v1 metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo2 - replicaCreateBackupComplete: true - stanzaCreated: true + name: 11-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/44-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/11-read-from-primary.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/44-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/11-read-from-primary.yaml diff --git a/e2e-tests/tests/major-upgrade/40-15-to-16.yaml b/e2e-tests/tests/major-upgrade/12-15-to-16.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/40-15-to-16.yaml rename to e2e-tests/tests/major-upgrade/12-15-to-16.yaml diff --git a/e2e-tests/tests/major-upgrade/12-assert.yaml b/e2e-tests/tests/major-upgrade/12-assert.yaml index d1790eabf5..8cd5dbcad3 100644 --- a/e2e-tests/tests/major-upgrade/12-assert.yaml +++ b/e2e-tests/tests/major-upgrade/12-assert.yaml @@ -1,15 +1,38 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 660 +timeout: 360 +commands: +- script: |- + kubectl -n ${NAMESPACE} get pg,pod,job + sleep 5 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: major-upgrade +spec: + postgresVersion: 16 +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready --- kind: Job apiVersion: batch/v1 metadata: - annotations: - postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-12-to-13 labels: - postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo2 + postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo3 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -17,15 +40,3 @@ metadata: blockOwnerDeletion: true status: succeeded: 1 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGBackup -metadata: - name: backup-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo2 - options: - - --type=full -status: - state: Succeeded diff --git a/e2e-tests/tests/major-upgrade/12-run-backup.yaml b/e2e-tests/tests/major-upgrade/12-run-backup.yaml deleted file mode 100644 index 601008d4ca..0000000000 --- a/e2e-tests/tests/major-upgrade/12-run-backup.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGBackup -metadata: - name: backup-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo2 - options: - - --type=full diff --git a/e2e-tests/tests/major-upgrade/13-assert.yaml b/e2e-tests/tests/major-upgrade/13-assert.yaml index 2d05bb7d88..6af985e4b7 100644 --- a/e2e-tests/tests/major-upgrade/13-assert.yaml +++ b/e2e-tests/tests/major-upgrade/13-assert.yaml @@ -1,52 +1,21 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 720 +timeout: 660 commands: - script: |- - set -o errexit - - kubectl -n ${NAMESPACE} get pod - - for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do - phase=$(kubectl -n ${NAMESPACE} get pod/${pod} -o jsonpath={".status.phase"}) - if [[ "${phase}" != "Running" ]]; then - echo "Waiting for ${pod} to start running" - continue - fi - echo "PostgreSQL logs from ${pod}:" - echo "find /pgdata/pg13/log -type f -iname 'postgresql*.log' -exec tail -n 30 {} \;" \ - | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null - done - - sleep 30 -collectors: -- type: pod - selector: "postgres-operator.crunchydata.com/data=postgres" - tail: 30 + kubectl get postgrescluster major-upgrade \ + -n ${NAMESPACE} \ + -o yaml \ + | yq eval '.status.pgbackrest.repos' - --- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo2 -status: - state: Succeeded ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster metadata: name: major-upgrade status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready + pgbackrest: + repos: + - bound: true + name: repo4 + replicaCreateBackupComplete: true + stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/31-change-repo.yaml b/e2e-tests/tests/major-upgrade/13-change-repo.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/31-change-repo.yaml rename to e2e-tests/tests/major-upgrade/13-change-repo.yaml diff --git a/e2e-tests/tests/major-upgrade/13-run-restore.yaml b/e2e-tests/tests/major-upgrade/13-run-restore.yaml deleted file mode 100644 index bba96fe985..0000000000 --- a/e2e-tests/tests/major-upgrade/13-run-restore.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-12-to-13 -spec: - pgCluster: major-upgrade - repoName: repo2 diff --git a/e2e-tests/tests/major-upgrade/14-assert.yaml b/e2e-tests/tests/major-upgrade/14-assert.yaml index 7c65443fbe..55610fcd16 100644 --- a/e2e-tests/tests/major-upgrade/14-assert.yaml +++ b/e2e-tests/tests/major-upgrade/14-assert.yaml @@ -1,10 +1,31 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 30 +timeout: 660 --- -kind: ConfigMap -apiVersion: v1 +kind: Job +apiVersion: batch/v1 metadata: - name: 05-read-from-primary -data: - data: ' 100500' + annotations: + postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-15-to-16 + labels: + postgres-operator.crunchydata.com/pgbackrest-backup: manual + postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGBackup +metadata: + name: backup-after-15-to-16 +spec: + pgCluster: major-upgrade + repoName: repo4 + options: + - --type=full +status: + state: Succeeded diff --git a/e2e-tests/tests/major-upgrade/14-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/14-read-from-primary.yaml deleted file mode 100644 index ac80bb337c..0000000000 --- a/e2e-tests/tests/major-upgrade/14-read-from-primary.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -timeout: 30 -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - - kubectl create configmap -n "${NAMESPACE}" 05-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/42-run-backup.yaml b/e2e-tests/tests/major-upgrade/14-run-backup.yaml similarity index 89% rename from e2e-tests/tests/major-upgrade/42-run-backup.yaml rename to e2e-tests/tests/major-upgrade/14-run-backup.yaml index 3e4fe9c94c..adc6c49ed2 100644 --- a/e2e-tests/tests/major-upgrade/42-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade/14-run-backup.yaml @@ -4,6 +4,6 @@ metadata: name: backup-after-15-to-16 spec: pgCluster: major-upgrade - repoName: repo1 + repoName: repo4 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/44-assert.yaml b/e2e-tests/tests/major-upgrade/15-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/44-assert.yaml rename to e2e-tests/tests/major-upgrade/15-assert.yaml index 95d57c293f..3590bbe99a 100644 --- a/e2e-tests/tests/major-upgrade/44-assert.yaml +++ b/e2e-tests/tests/major-upgrade/15-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 11-read-from-primary + name: 15-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/34-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/15-read-from-primary.yaml similarity index 85% rename from e2e-tests/tests/major-upgrade/34-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/15-read-from-primary.yaml index 12ff6f8d79..23a10ac997 100644 --- a/e2e-tests/tests/major-upgrade/34-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/15-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 09-read-from-primary --from-literal=data="${data}" \ No newline at end of file + kubectl create configmap -n "${NAMESPACE}" 15-read-from-primary --from-literal=data="${data}" \ No newline at end of file diff --git a/e2e-tests/tests/major-upgrade/45-16-to-17.yaml b/e2e-tests/tests/major-upgrade/16-16-to-17.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/45-16-to-17.yaml rename to e2e-tests/tests/major-upgrade/16-16-to-17.yaml diff --git a/e2e-tests/tests/major-upgrade/45-assert.yaml b/e2e-tests/tests/major-upgrade/16-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/45-assert.yaml rename to e2e-tests/tests/major-upgrade/16-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/31-assert.yaml b/e2e-tests/tests/major-upgrade/17-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/31-assert.yaml rename to e2e-tests/tests/major-upgrade/17-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/32-assert.yaml b/e2e-tests/tests/major-upgrade/18-assert.yaml similarity index 93% rename from e2e-tests/tests/major-upgrade/32-assert.yaml rename to e2e-tests/tests/major-upgrade/18-assert.yaml index 75daf8364c..0bc5ed7dcc 100644 --- a/e2e-tests/tests/major-upgrade/32-assert.yaml +++ b/e2e-tests/tests/major-upgrade/18-assert.yaml @@ -6,7 +6,7 @@ kind: Job apiVersion: batch/v1 metadata: annotations: - postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-14-to-15 + postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-16-to-17 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual postgres-operator.crunchydata.com/pgbackrest-repo: repo4 @@ -21,7 +21,7 @@ status: apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup metadata: - name: backup-after-14-to-15 + name: backup-after-16-to-17 spec: pgCluster: major-upgrade repoName: repo4 diff --git a/e2e-tests/tests/major-upgrade/47-run-backup.yaml b/e2e-tests/tests/major-upgrade/18-run-backup.yaml similarity index 89% rename from e2e-tests/tests/major-upgrade/47-run-backup.yaml rename to e2e-tests/tests/major-upgrade/18-run-backup.yaml index 392bc719ea..9a378656f4 100644 --- a/e2e-tests/tests/major-upgrade/47-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade/18-run-backup.yaml @@ -4,6 +4,6 @@ metadata: name: backup-after-16-to-17 spec: pgCluster: major-upgrade - repoName: repo1 + repoName: repo4 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/34-assert.yaml b/e2e-tests/tests/major-upgrade/19-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/34-assert.yaml rename to e2e-tests/tests/major-upgrade/19-assert.yaml index 7321c61abe..381403d405 100644 --- a/e2e-tests/tests/major-upgrade/34-assert.yaml +++ b/e2e-tests/tests/major-upgrade/19-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 09-read-from-primary + name: 19-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/49-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml similarity index 85% rename from e2e-tests/tests/major-upgrade/49-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade/19-read-from-primary.yaml index 03c7aa852b..f835a311f5 100644 --- a/e2e-tests/tests/major-upgrade/49-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml @@ -9,4 +9,4 @@ commands: source ../../functions data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 11-read-from-primary --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 19-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/23-assert.yaml b/e2e-tests/tests/major-upgrade/23-assert.yaml deleted file mode 100644 index 75b542e689..0000000000 --- a/e2e-tests/tests/major-upgrade/23-assert.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 720 -commands: -- script: |- - set -o errexit - - kubectl -n ${NAMESPACE} get pod - - for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do - phase=$(kubectl -n ${NAMESPACE} get pod/${pod} -o jsonpath={".status.phase"}) - if [[ "${phase}" != "Running" ]]; then - echo "Waiting for ${pod} to start running" - continue - fi - echo "PostgreSQL logs from ${pod}:" - echo "find /pgdata/pg14/log -type f -iname 'postgresql*.log' -exec tail -n 30 {} \;" \ - | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null - done - - sleep 30 -collectors: -- type: pod - selector: "postgres-operator.crunchydata.com/data=postgres" - tail: 30 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-13-to-14 -spec: - pgCluster: major-upgrade - repoName: repo3 -status: - state: Succeeded ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: major-upgrade -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready diff --git a/e2e-tests/tests/major-upgrade/23-run-restore.yaml b/e2e-tests/tests/major-upgrade/23-run-restore.yaml deleted file mode 100644 index 079ebf7b77..0000000000 --- a/e2e-tests/tests/major-upgrade/23-run-restore.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-13-to-14 -spec: - pgCluster: major-upgrade - repoName: repo3 diff --git a/e2e-tests/tests/major-upgrade/33-assert.yaml b/e2e-tests/tests/major-upgrade/33-assert.yaml deleted file mode 100644 index 1d3a8a9aae..0000000000 --- a/e2e-tests/tests/major-upgrade/33-assert.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 720 -commands: -- script: |- - set -o errexit - - kubectl -n ${NAMESPACE} get pod - - for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do - phase=$(kubectl -n ${NAMESPACE} get pod/${pod} -o jsonpath={".status.phase"}) - if [[ "${phase}" != "Running" ]]; then - echo "Waiting for ${pod} to start running" - continue - fi - echo "PostgreSQL logs from ${pod}:" - echo "find /pgdata/pg15/log -type f -iname 'postgresql*.log' -exec tail -n 30 {} \;" \ - | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null - done - - sleep 30 -collectors: -- type: pod - selector: "postgres-operator.crunchydata.com/data=postgres" - tail: 30 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-14-to-15 -spec: - pgCluster: major-upgrade - repoName: repo4 -status: - state: Succeeded ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: major-upgrade -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready diff --git a/e2e-tests/tests/major-upgrade/33-run-restore.yaml b/e2e-tests/tests/major-upgrade/33-run-restore.yaml deleted file mode 100644 index 8e7c7c6dab..0000000000 --- a/e2e-tests/tests/major-upgrade/33-run-restore.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-14-to-15 -spec: - pgCluster: major-upgrade - repoName: repo4 - diff --git a/e2e-tests/tests/major-upgrade/40-assert.yaml b/e2e-tests/tests/major-upgrade/40-assert.yaml deleted file mode 100644 index de3a338c83..0000000000 --- a/e2e-tests/tests/major-upgrade/40-assert.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 360 -commands: -- script: |- - kubectl -n ${NAMESPACE} get pg,pod,job - sleep 5 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: major-upgrade -spec: - postgresVersion: 16 -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready ---- -kind: Job -apiVersion: batch/v1 -metadata: - labels: - postgres-operator.crunchydata.com/cluster: major-upgrade - postgres-operator.crunchydata.com/pgbackrest: '' - postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 - ownerReferences: - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGBackup - controller: true - blockOwnerDeletion: true -status: - succeeded: 1 diff --git a/e2e-tests/tests/major-upgrade/41-assert.yaml b/e2e-tests/tests/major-upgrade/41-assert.yaml deleted file mode 100644 index 1b95780c8f..0000000000 --- a/e2e-tests/tests/major-upgrade/41-assert.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo1 - replicaCreateBackupComplete: true - stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/41-change-repo.yaml b/e2e-tests/tests/major-upgrade/41-change-repo.yaml deleted file mode 100644 index d3d277599f..0000000000 --- a/e2e-tests/tests/major-upgrade/41-change-repo.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - kubectl patch \ - -n $NAMESPACE \ - perconapgcluster major-upgrade \ - --type='json' \ - -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo1"}]' diff --git a/e2e-tests/tests/major-upgrade/42-assert.yaml b/e2e-tests/tests/major-upgrade/42-assert.yaml deleted file mode 100644 index 2b003b69a9..0000000000 --- a/e2e-tests/tests/major-upgrade/42-assert.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 ---- -kind: Job -apiVersion: batch/v1 -metadata: - annotations: - postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-15-to-16 - labels: - postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo1 - ownerReferences: - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGBackup - controller: true - blockOwnerDeletion: true -status: - succeeded: 1 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGBackup -metadata: - name: backup-after-15-to-16 -spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --type=full -status: - state: Succeeded diff --git a/e2e-tests/tests/major-upgrade/43-assert.yaml b/e2e-tests/tests/major-upgrade/43-assert.yaml deleted file mode 100644 index 3114c23118..0000000000 --- a/e2e-tests/tests/major-upgrade/43-assert.yaml +++ /dev/null @@ -1,52 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 720 -commands: -- script: |- - set -o errexit - - kubectl -n ${NAMESPACE} get pod - - for pod in $(kubectl -n ${NAMESPACE} get pods -l postgres-operator.crunchydata.com/data=postgres --no-headers | awk '{print $1}'); do - phase=$(kubectl -n ${NAMESPACE} get pod/${pod} -o jsonpath={".status.phase"}) - if [[ "${phase}" != "Running" ]]; then - echo "Waiting for ${pod} to start running" - continue - fi - echo "PostgreSQL logs from ${pod}:" - echo "find /pgdata/pg16/log -type f -iname 'postgresql*.log' -exec tail -n 30 {} \;" \ - | kubectl -n ${NAMESPACE} exec -it ${pod} -- bash 2>/dev/null - done - - sleep 30 -collectors: -- type: pod - selector: "postgres-operator.crunchydata.com/data=postgres" - tail: 30 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-15-to-16 -spec: - pgCluster: major-upgrade - repoName: repo1 -status: - state: Succeeded ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: major-upgrade -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready diff --git a/e2e-tests/tests/major-upgrade/43-run-restore.yaml b/e2e-tests/tests/major-upgrade/43-run-restore.yaml deleted file mode 100644 index c86adba0d1..0000000000 --- a/e2e-tests/tests/major-upgrade/43-run-restore.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-15-to-16 -spec: - pgCluster: major-upgrade - repoName: repo1 - diff --git a/e2e-tests/tests/major-upgrade/47-assert.yaml b/e2e-tests/tests/major-upgrade/47-assert.yaml deleted file mode 100644 index 0b0618774c..0000000000 --- a/e2e-tests/tests/major-upgrade/47-assert.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 ---- -kind: Job -apiVersion: batch/v1 -metadata: - annotations: - postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-16-to-17 - labels: - postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo1 - ownerReferences: - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGBackup - controller: true - blockOwnerDeletion: true -status: - succeeded: 1 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGBackup -metadata: - name: backup-after-16-to-17 -spec: - pgCluster: major-upgrade - repoName: repo1 - options: - - --type=full -status: - state: Succeeded diff --git a/e2e-tests/tests/major-upgrade/48-assert.yaml b/e2e-tests/tests/major-upgrade/48-assert.yaml deleted file mode 100644 index 95d57c293f..0000000000 --- a/e2e-tests/tests/major-upgrade/48-assert.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 30 ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: 11-read-from-primary -data: - data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/48-run-restore.yaml b/e2e-tests/tests/major-upgrade/48-run-restore.yaml deleted file mode 100644 index d496fe3126..0000000000 --- a/e2e-tests/tests/major-upgrade/48-run-restore.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGRestore -metadata: - name: restore-after-16-to-17 -spec: - pgCluster: major-upgrade - repoName: repo1 - From f2b450ae3ed613c03ef4338be046ff12863894b9 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 12 Nov 2025 17:04:41 +0200 Subject: [PATCH 210/300] K8SPG-893 configure LC_ALL and LANG for database containers (#1350) * K8SPG-893 configure LC_ALL and LANG for database containers * copy env from database to upgrade container * fix tests * guard with version 2.8 * fix * set version to latest for unit test pod allow volume grow * add only the needed env vars instead of the whole database env * fix unit test --- internal/controller/pgupgrade/jobs.go | 14 ++++++++++++++ internal/controller/pgupgrade/jobs_test.go | 5 +++++ internal/postgres/config.go | 15 +++++++++++++++ internal/postgres/reconcile_test.go | 18 +++++++++++++++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/internal/controller/pgupgrade/jobs.go b/internal/controller/pgupgrade/jobs.go index 9ce675f89b..3d74379d10 100644 --- a/internal/controller/pgupgrade/jobs.go +++ b/internal/controller/pgupgrade/jobs.go @@ -203,6 +203,20 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( SecurityContext: database.SecurityContext, VolumeMounts: volumeMounts, // K8SPG-254 + // K8SPG-893 + Env: []corev1.EnvVar{ + // Critical for major upgrades to avoid lc_collate mismatches. + // - https://www.postgresql.org/docs/current/locale.html + { + Name: "LC_ALL", + Value: "en_US.utf-8", + }, + { + Name: "LANG", + Value: "en_US.utf-8", + }, + }, + // Use our upgrade command and the specified image and resources. Command: upgradeCommand( upgrade.Spec.FromPostgresVersion, diff --git a/internal/controller/pgupgrade/jobs_test.go b/internal/controller/pgupgrade/jobs_test.go index 79075b1c24..992503b7ff 100644 --- a/internal/controller/pgupgrade/jobs_test.go +++ b/internal/controller/pgupgrade/jobs_test.go @@ -203,6 +203,11 @@ spec: - upgrade - "19" - "25" + env: + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 image: img4 name: database resources: diff --git a/internal/postgres/config.go b/internal/postgres/config.go index 1ac7b38a86..feda6d8aa1 100644 --- a/internal/postgres/config.go +++ b/internal/postgres/config.go @@ -164,6 +164,21 @@ func Environment(cluster *v1beta1.PostgresCluster) []corev1.EnvVar { }) } + if cluster.CompareVersion("2.8.0") >= 0 { + env = append(env, []corev1.EnvVar{ + // Critical for major upgrades to avoid lc_collate mismatches. + // - https://www.postgresql.org/docs/current/locale.html + { + Name: "LC_ALL", + Value: "en_US.utf-8", + }, + { + Name: "LANG", + Value: "en_US.utf-8", + }, + }...) + } + return env } diff --git a/internal/postgres/reconcile_test.go b/internal/postgres/reconcile_test.go index 17da5bf3ff..1a3f0dba95 100644 --- a/internal/postgres/reconcile_test.go +++ b/internal/postgres/reconcile_test.go @@ -138,6 +138,10 @@ containers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: database ports: @@ -289,6 +293,10 @@ initContainers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: postgres-startup resources: @@ -713,7 +721,7 @@ func TestInstancePodAllowVolumeGrow(t *testing.T) { cluster.Spec.ImagePullPolicy = corev1.PullAlways cluster.Spec.PostgresVersion = 11 cluster.SetLabels(map[string]string{ - naming.LabelVersion: "2.7.0", + naming.LabelVersion: version.Version(), }) dataVolume := new(corev1.PersistentVolumeClaim) @@ -781,6 +789,10 @@ containers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: database ports: @@ -946,6 +958,10 @@ initContainers: value: /tmp - name: LDAPTLS_CACERT value: /etc/postgres/ldap/ca.crt + - name: LC_ALL + value: en_US.utf-8 + - name: LANG + value: en_US.utf-8 imagePullPolicy: Always name: postgres-startup resources: From 0d947b20aa5d2f28b51020121844b3a2b0df5555 Mon Sep 17 00:00:00 2001 From: George Kechagias Date: Wed, 12 Nov 2025 20:38:50 +0200 Subject: [PATCH 211/300] K8SPG-894 upgrade job using the init container from primary sts (#1351) * K8SPG-894 upgrade job using the init container from primary sts * update unit test * configure custom container for the upgrade spec and ensure that everything is considered * change order of init containers * small refactor --- internal/controller/pgupgrade/jobs.go | 18 ++++++++++++++++-- internal/controller/pgupgrade/jobs_test.go | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/internal/controller/pgupgrade/jobs.go b/internal/controller/pgupgrade/jobs.go index 3d74379d10..93b2bad34d 100644 --- a/internal/controller/pgupgrade/jobs.go +++ b/internal/controller/pgupgrade/jobs.go @@ -189,8 +189,22 @@ func (r *PGUpgradeReconciler) generateUpgradeJob( // Replace all containers with one that does the upgrade. job.Spec.Template.Spec.EphemeralContainers = nil - // K8SPG-254: Major upgrade support - job.Spec.Template.Spec.InitContainers = upgrade.Spec.InitContainers + // K8SPG-894: Ensure database init container is included for required scripts + var initContainers []corev1.Container + + dbInitContainerName := ContainerDatabase + "-init" + for _, container := range startup.Spec.Template.Spec.InitContainers { + if container.Name == dbInitContainerName { + initContainers = append(initContainers, container) + break + } + } + + if len(upgrade.Spec.InitContainers) > 0 { + initContainers = append(initContainers, upgrade.Spec.InitContainers...) + } + + job.Spec.Template.Spec.InitContainers = initContainers volumeMounts := database.VolumeMounts volumeMounts = append(volumeMounts, upgrade.Spec.VolumeMounts...) diff --git a/internal/controller/pgupgrade/jobs_test.go b/internal/controller/pgupgrade/jobs_test.go index 992503b7ff..7f1e5a32b6 100644 --- a/internal/controller/pgupgrade/jobs_test.go +++ b/internal/controller/pgupgrade/jobs_test.go @@ -110,9 +110,19 @@ func TestGenerateUpgradeJob(t *testing.T) { upgrade.Spec.Resources.Requests = corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("3.14"), } + upgrade.Spec.InitContainers = []corev1.Container{ + { + Name: "upgrade-init-container", + }, + } startup := &appsv1.StatefulSet{} startup.Spec.Template.Spec = corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: ContainerDatabase + "-init", + }, + }, Containers: []corev1.Container{{ Name: ContainerDatabase, @@ -218,6 +228,11 @@ spec: volumeMounts: - mountPath: /mnt/some/such name: vm1 + initContainers: + - name: database-init + resources: {} + - name: upgrade-init-container + resources: {} restartPolicy: Never volumes: - hostPath: From 751f084377b5938f48fea8a2b4a863ad8470ea45 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Fri, 14 Nov 2025 00:35:33 +0200 Subject: [PATCH 212/300] Revert images back to main after 2.8.0 release (#1353) * Revert images back to main after 2.8.0 release * Fix consistency and pg main image --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Makefile | 9 +++++++-- config/bundle/kustomization.yaml | 4 ++-- .../versionlabel_in_perconapgbackups.yaml | 2 +- .../versionlabel_in_perconapgclusters.yaml | 2 +- .../versionlabel_in_perconapgrestores.yaml | 2 +- .../versionlabel_in_perconapgupgrade.yaml | 2 +- config/cw-bundle/kustomization.yaml | 4 ++-- config/manager/cluster/kustomization.yaml | 4 ++-- config/manager/namespace/kustomization.yaml | 4 ++-- deploy/bundle.yaml | 10 +++++----- deploy/cr.yaml | 18 +++++++++--------- deploy/crd.yaml | 8 ++++---- deploy/cw-bundle.yaml | 10 +++++----- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 ++++---- e2e-tests/functions | 12 ++++++++++++ e2e-tests/tests/init-deploy/05-assert.yaml | 12 ++++++------ .../tests/upgrade-consistency/01-assert.yaml | 2 +- .../upgrade-consistency/01-create-cluster.yaml | 15 ++++++++++----- .../tests/upgrade-consistency/02-assert.yaml | 2 +- .../upgrade-consistency/02-patch-cluster.yaml | 15 ++++++++++----- .../tests/upgrade-consistency/03-assert.yaml | 2 +- .../upgrade-consistency/03-patch-cluster.yaml | 3 ++- .../tests/upgrade-minor/01-create-cluster.yaml | 7 +++---- e2e-tests/vars.sh | 2 +- .../testdata/sidecar-resources-cr.yaml | 2 +- percona/version/version.txt | 2 +- 28 files changed, 97 insertions(+), 70 deletions(-) diff --git a/Makefile b/Makefile index 528b983dbb..72854a544f 100644 --- a/Makefile +++ b/Makefile @@ -443,6 +443,9 @@ rm -rf $$TMP_DIR ;\ } endef +update-version: + echo $(NEXT_VER) > percona/version/version.txt + # Prepare release PG_VER ?= $(shell grep -o "postgresVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+") include e2e-tests/release_versions @@ -469,11 +472,11 @@ MINOR_VER := $(word 2,$(subst ., ,$(CURRENT_VERSION))) NEXT_VER := $(MAJOR_VER).$(shell expr $(MINOR_VER) + 1).0 PREV1_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 1).0 PREV2_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 2).0 -after-release: generate - echo $(NEXT_VER) > percona/version/version.txt +after-release: update-version generate $(SED) -i \ -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(NEXT_VER)/}" \ -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ + -e "/initContainer:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" \ -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ @@ -484,6 +487,8 @@ after-release: generate -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" deploy/upgrade.yaml + +# Update upgrade-consistency $(SED) -i "s/$(PREV2_VERSION)/$(PREV1_VERSION)/g" e2e-tests/tests/upgrade-consistency/01-*.yaml $(SED) -i "s/$(PREV1_VERSION)/$(CURRENT_VERSION)/g" e2e-tests/tests/upgrade-consistency/02-*.yaml $(SED) -i "s/$(CURRENT_VERSION)/$(NEXT_VER)/g" e2e-tests/tests/upgrade-consistency/03-*.yaml e2e-tests/tests/init-deploy/05-assert.yaml \ No newline at end of file diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index 0412fd1ddd..90cf89956e 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -6,5 +6,5 @@ resources: - ../manager/namespace images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/crd/patches/versionlabel_in_perconapgbackups.yaml b/config/crd/patches/versionlabel_in_perconapgbackups.yaml index d4c5958860..3c32866138 100644 --- a/config/crd/patches/versionlabel_in_perconapgbackups.yaml +++ b/config/crd/patches/versionlabel_in_perconapgbackups.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgbackups.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgclusters.yaml b/config/crd/patches/versionlabel_in_perconapgclusters.yaml index 9ee2cce213..8a4bf1231a 100644 --- a/config/crd/patches/versionlabel_in_perconapgclusters.yaml +++ b/config/crd/patches/versionlabel_in_perconapgclusters.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgclusters.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgrestores.yaml b/config/crd/patches/versionlabel_in_perconapgrestores.yaml index 9d4796443f..b9c11c6953 100644 --- a/config/crd/patches/versionlabel_in_perconapgrestores.yaml +++ b/config/crd/patches/versionlabel_in_perconapgrestores.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgrestores.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml index 75d0fce2bb..0becb36acf 100644 --- a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml +++ b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgupgrades.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 0b3c810eab..440d098731 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -7,5 +7,5 @@ resources: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index 940a80d27b..6f8f4bf129 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -8,5 +8,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 1e4cfc0e67..a57ff786e0 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -9,5 +9,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 020076242b..fa440143fd 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53964,7 +53964,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index ed3064d5d1..bdd17d33fb 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,9 +9,9 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: 2.8.0 + crVersion: 2.9.0 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: docker.io/percona/percona-distribution-postgresql:17.6-1 + image: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -188,7 +188,7 @@ spec: # - secretRef: # name: instance-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -312,7 +312,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: docker.io/percona/percona-pgbouncer:1.24.1-1 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 # env: # - name: MY_ENV # value: "1000" @@ -409,7 +409,7 @@ spec: pgbackrest: # metadata: # labels: - image: docker.io/percona/percona-pgbackrest:2.56.0-1 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 # env: # - name: MY_ENV # value: "1000" @@ -417,7 +417,7 @@ spec: # - secretRef: # name: repo-host-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -613,7 +613,7 @@ spec: pmm: enabled: false - image: docker.io/percona/pmm-client:3.4.1 + image: docker.io/perconalab/pmm-client:dev-latest # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -647,7 +647,7 @@ spec: # - basebackup # extensions: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/perconalab/percona-postgresql-operator:main # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/crd.yaml b/deploy/crd.yaml index be4cee1441..b0bf292f26 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 3fc6cc1c48..5e19e282f1 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.5 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53962,7 +53962,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 1abc72e4c5..7861413845 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 7da02aca8d..c6c492333b 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 2a28427a41..59ddf91d3b 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: docker.io/percona/percona-postgresql-operator:2.8.0-upgrade + image: docker.io/perconalab/percona-postgresql-operator:main-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.6-1 - toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.24.1-1 - toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.56.0-1 + toPostgresImage: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres + toPgBouncerImage: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 + toPgBackRestImage: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 diff --git a/e2e-tests/functions b/e2e-tests/functions index ecdb008d13..6b2a23167e 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -495,6 +495,18 @@ get_service_ip() { kubectl get service/$service -n "${NAMESPACE}" -o 'jsonpath={.status.loadBalancer.ingress[].hostname}' } +get_version_images() { + local cr_version="$1" + local component="$2" + local release_versions_file="${TEMP_DIR}/release_version_${cr_version}" + + if [[ ! -f $release_versions_file ]]; then + curl -s "https://raw.githubusercontent.com/percona/percona-postgresql-operator/refs/tags/v${cr_version}/e2e-tests/release_versions" >$release_versions_file + fi + + grep -i ${component} $release_versions_file | cut -d'=' -f2 +} + wait_for_delete() { local res="$1" diff --git a/e2e-tests/tests/init-deploy/05-assert.yaml b/e2e-tests/tests/init-deploy/05-assert.yaml index 246ab59daf..86b1aa02c3 100644 --- a/e2e-tests/tests/init-deploy/05-assert.yaml +++ b/e2e-tests/tests/init-deploy/05-assert.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -81,7 +81,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -144,7 +144,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -168,7 +168,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -191,7 +191,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" @@ -214,7 +214,7 @@ spec: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" diff --git a/e2e-tests/tests/upgrade-consistency/01-assert.yaml b/e2e-tests/tests/upgrade-consistency/01-assert.yaml index 60b019bcef..f50e94bdae 100644 --- a/e2e-tests/tests/upgrade-consistency/01-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-assert.yaml @@ -122,7 +122,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.6.0 + crVersion: 2.7.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml index 53c32fbcbe..e0c05f018f 100644 --- a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml @@ -8,10 +8,15 @@ commands: source ../../functions - cr_version="2.6.0" + cr_version="2.7.0" + + backrest_image=$(get_version_images $cr_version BACKREST${PG_VER}) + pgbouncer_image=$(get_version_images $cr_version PGBOUNCER${PG_VER}) + postgres_image=$(get_version_images $cr_version POSTGRESQL${PG_VER}) + get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ - | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ - | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-pgbackrest\"" - \ - | yq eval ".spec.proxy.pgBouncer.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-pgbouncer\"" - \ - | kubectl -n "${NAMESPACE}" apply -f - + | yq eval ".spec.image=\"${REGISTRY_NAME_FULL}${postgres_image}\"" - \ + | yq eval ".spec.backups.pgbackrest.image=\"${REGISTRY_NAME_FULL}${backrest_image}\"" - \ + | yq eval ".spec.proxy.pgBouncer.image=\"${REGISTRY_NAME_FULL}${pgbouncer_image}\"" - \ + | kubectl -n "${NAMESPACE}" apply -f - \ No newline at end of file diff --git a/e2e-tests/tests/upgrade-consistency/02-assert.yaml b/e2e-tests/tests/upgrade-consistency/02-assert.yaml index 4bce8de813..3d3961691b 100644 --- a/e2e-tests/tests/upgrade-consistency/02-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.7.0 + crVersion: 2.8.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index f35c4dd88d..54c3b9853f 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -8,12 +8,17 @@ commands: source ../../functions - cr_version="2.7.0" + cr_version="2.8.0" + + backrest_image=$(get_version_images $cr_version BACKREST${PG_VER} ) + pgbouncer_image=$(get_version_images $cr_version PGBOUNCER${PG_VER}) + postgres_image=$(get_version_images $cr_version POSTGRESQL${PG_VER}) + get_cr \ - | yq eval ".spec.crVersion=\"$cr_version\"" - \ - \ - | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ - | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:pg-operator-$cr_version-pgbackrest$PG_VER\"" - \ - | yq eval ".spec.proxy.pgBouncer.image=\"${IMAGE_BASE}:pg-operator-$cr_version-pgbouncer$PG_VER\"" - \ + | yq eval ".spec.crVersion=\"$cr_version\"" - \ + | yq eval ".spec.image=\"${REGISTRY_NAME_FULL}${postgres_image}\"" - \ + | yq eval ".spec.backups.pgbackrest.image=\"${REGISTRY_NAME_FULL}${backrest_image}\"" - \ + | yq eval ".spec.proxy.pgBouncer.image=\"${REGISTRY_NAME_FULL}${pgbouncer_image}\"" - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 diff --git a/e2e-tests/tests/upgrade-consistency/03-assert.yaml b/e2e-tests/tests/upgrade-consistency/03-assert.yaml index bcc9f45111..1382b3ea26 100644 --- a/e2e-tests/tests/upgrade-consistency/03-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.8.0 + crVersion: 2.9.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 959d3aab14..51c335c9fc 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -8,7 +8,8 @@ commands: source ../../functions - cr_version="2.8.0" + cr_version="2.9.0" + get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ diff --git a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml index 9b96bfe43c..e7eb470636 100644 --- a/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-minor/01-create-cluster.yaml @@ -28,10 +28,9 @@ commands: $sed -E -i "s|^( *image: *)(.*)|\1${REGISTRY_NAME_FULL}\2|" ${TEMP_DIR}/cr_lower.yaml fi - lower_ver_images=$(curl -s https://raw.githubusercontent.com/percona/percona-postgresql-operator/refs/tags/v${lower_ver}/e2e-tests/release_versions) - backrest_image=$(echo "$lower_ver_images" | grep BACKREST${pg_ver} | cut -d'=' -f2 ) - pgbouncer_image=$(echo "$lower_ver_images" | grep PGBOUNCER${pg_ver} | cut -d'=' -f2 ) - postgres_image=$(echo "$lower_ver_images" | grep POSTGRESQL${pg_ver} | cut -d'=' -f2 ) + backrest_image=$(get_version_images $lower_ver BACKREST${pg_ver}) + pgbouncer_image=$(get_version_images $lower_ver PGBOUNCER${pg_ver}) + postgres_image=$(get_version_images $lower_ver POSTGRESQL${pg_ver}) yq -i eval ' .metadata.name = "'${test_name}'" | diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 42691936e0..6aaf2ce21b 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -30,7 +30,7 @@ else export PG_VER="${PG_VER:-17}" fi export IMAGE_PGBOUNCER=${IMAGE_PGBOUNCER:-"${IMAGE_BASE}:main-pgbouncer$PG_VER"} -export IMAGE_POSTGRESQL=${IMAGE_POSTGRESQL:-"perconalab/percona-distribution-postgresql:$PG_VER"} +export IMAGE_POSTGRESQL=${IMAGE_POSTGRESQL:-"${IMAGE_BASE}:main-ppg$PG_VER-postgres"} export IMAGE_BACKREST=${IMAGE_BACKREST:-"${IMAGE_BASE}:main-pgbackrest$PG_VER"} export IMAGE_UPGRADE=${IMAGE_UPGRADE:-"${IMAGE_BASE}:main-upgrade"} export BUCKET=${BUCKET:-"pg-operator-testing"} diff --git a/percona/controller/testdata/sidecar-resources-cr.yaml b/percona/controller/testdata/sidecar-resources-cr.yaml index 1c137a6ead..aa347ddfd9 100644 --- a/percona/controller/testdata/sidecar-resources-cr.yaml +++ b/percona/controller/testdata/sidecar-resources-cr.yaml @@ -4,7 +4,7 @@ kind: PerconaPGCluster metadata: name: cluster1 spec: - crVersion: 2.8.0 + crVersion: 2.9.0 image: perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always diff --git a/percona/version/version.txt b/percona/version/version.txt index 834f262953..c8e38b6140 100644 --- a/percona/version/version.txt +++ b/percona/version/version.txt @@ -1 +1 @@ -2.8.0 +2.9.0 From f36b46f155e947cbeae1520e136e9983490beb8e Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Fri, 14 Nov 2025 09:04:04 +0200 Subject: [PATCH 213/300] Run reviewdog manifests when base_ref is 'release-' --- .github/workflows/reviewdog.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 921c73146c..a0a4a1e058 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -94,12 +94,12 @@ jobs: steps: - uses: actions/checkout@v5 - name: check on release branch - if: ${{ contains(github.head_ref, 'release-') || contains(github.base_ref, 'release-') }} + if: ${{ contains(github.base_ref, 'release-') }} run: | make generate VERSION="$(cat percona/version/version.txt)" IMAGE_TAG_BASE="percona/percona-postgresql-operator" git diff --exit-code - name: check on non release branches - if: ${{ ! (contains(github.head_ref, 'release-') || contains(github.base_ref, 'release-')) }} + if: ${{ ! contains(github.base_ref, 'release-') }} run: | make generate VERSION=main git diff --exit-code From 3adc81268ba648f2d40181ba59852b4ca2acf74e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 22:42:55 +0200 Subject: [PATCH 214/300] CLOUD-727: Bump github.com/go-openapi/runtime from 0.29.0 to 0.29.2 (#1348) Bumps [github.com/go-openapi/runtime](https://github.com/go-openapi/runtime) from 0.29.0 to 0.29.2. - [Release notes](https://github.com/go-openapi/runtime/releases) - [Commits](https://github.com/go-openapi/runtime/compare/v0.29.0...v0.29.2) --- updated-dependencies: - dependency-name: github.com/go-openapi/runtime dependency-version: 0.29.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 21 ++++++++++----------- go.sum | 46 ++++++++++++++++++++++++---------------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/go.mod b/go.mod index 9561d75171..fd929899fb 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.25.1 require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc github.com/go-logr/logr v1.4.3 - github.com/go-openapi/errors v0.22.3 - github.com/go-openapi/runtime v0.29.0 - github.com/go-openapi/strfmt v0.24.0 + github.com/go-openapi/errors v0.22.4 + github.com/go-openapi/runtime v0.29.2 + github.com/go-openapi/strfmt v0.25.0 github.com/go-openapi/swag v0.25.1 - github.com/go-openapi/validate v0.25.0 + github.com/go-openapi/validate v0.25.1 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.7.0 @@ -74,7 +74,6 @@ require ( ) require ( - github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go v1.55.8 github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect @@ -85,11 +84,11 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect - github.com/go-openapi/analysis v0.24.0 // indirect + github.com/go-openapi/analysis v0.24.1 // indirect github.com/go-openapi/jsonpointer v0.22.1 // indirect - github.com/go-openapi/jsonreference v0.21.2 // indirect - github.com/go-openapi/loads v0.23.1 // indirect - github.com/go-openapi/spec v0.22.0 // indirect + github.com/go-openapi/jsonreference v0.21.3 // indirect + github.com/go-openapi/loads v0.23.2 // indirect + github.com/go-openapi/spec v0.22.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang/protobuf v1.5.4 // indirect @@ -117,7 +116,7 @@ require ( github.com/swaggest/assertjson v1.9.0 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect - go.mongodb.org/mongo-driver v1.17.4 // indirect + go.mongodb.org/mongo-driver v1.17.6 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect @@ -125,7 +124,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.46.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.17.0 // indirect + golang.org/x/sync v0.18.0 // indirect golang.org/x/sys v0.37.0 // indirect golang.org/x/term v0.36.0 // indirect golang.org/x/text v0.30.0 // indirect diff --git a/go.sum b/go.sum index 07a898ce09..9f05daeab5 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,6 @@ github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcb github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc/go.mod h1:dOzRkbUNd/qpn35nOSy60ZQBiP9wa9g1kh9kaMg/tOk= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= -github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.55.8 h1:JRmEUbU52aJQZ2AjX4q4Wu7t4uZjOu71uyNmaWlUkJQ= github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -49,22 +47,22 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/analysis v0.24.0 h1:vE/VFFkICKyYuTWYnplQ+aVr45vlG6NcZKC7BdIXhsA= -github.com/go-openapi/analysis v0.24.0/go.mod h1:GLyoJA+bvmGGaHgpfeDh8ldpGo69fAJg7eeMDMRCIrw= -github.com/go-openapi/errors v0.22.3 h1:k6Hxa5Jg1TUyZnOwV2Lh81j8ayNw5VVYLvKrp4zFKFs= -github.com/go-openapi/errors v0.22.3/go.mod h1:+WvbaBBULWCOna//9B9TbLNGSFOfF8lY9dw4hGiEiKQ= +github.com/go-openapi/analysis v0.24.1 h1:Xp+7Yn/KOnVWYG8d+hPksOYnCYImE3TieBa7rBOesYM= +github.com/go-openapi/analysis v0.24.1/go.mod h1:dU+qxX7QGU1rl7IYhBC8bIfmWQdX4Buoea4TGtxXY84= +github.com/go-openapi/errors v0.22.4 h1:oi2K9mHTOb5DPW2Zjdzs/NIvwi2N3fARKaTJLdNabaM= +github.com/go-openapi/errors v0.22.4/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk= github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= -github.com/go-openapi/jsonreference v0.21.2 h1:Wxjda4M/BBQllegefXrY/9aq1fxBA8sI5M/lFU6tSWU= -github.com/go-openapi/jsonreference v0.21.2/go.mod h1:pp3PEjIsJ9CZDGCNOyXIQxsNuroxm8FAJ/+quA0yKzQ= -github.com/go-openapi/loads v0.23.1 h1:H8A0dX2KDHxDzc797h0+uiCZ5kwE2+VojaQVaTlXvS0= -github.com/go-openapi/loads v0.23.1/go.mod h1:hZSXkyACCWzWPQqizAv/Ye0yhi2zzHwMmoXQ6YQml44= -github.com/go-openapi/runtime v0.29.0 h1:Y7iDTFarS9XaFQ+fA+lBLngMwH6nYfqig1G+pHxMRO0= -github.com/go-openapi/runtime v0.29.0/go.mod h1:52HOkEmLL/fE4Pg3Kf9nxc9fYQn0UsIWyGjGIJE9dkg= -github.com/go-openapi/spec v0.22.0 h1:xT/EsX4frL3U09QviRIZXvkh80yibxQmtoEvyqug0Tw= -github.com/go-openapi/spec v0.22.0/go.mod h1:K0FhKxkez8YNS94XzF8YKEMULbFrRw4m15i2YUht4L0= -github.com/go-openapi/strfmt v0.24.0 h1:dDsopqbI3wrrlIzeXRbqMihRNnjzGC+ez4NQaAAJLuc= -github.com/go-openapi/strfmt v0.24.0/go.mod h1:Lnn1Bk9rZjXxU9VMADbEEOo7D7CDyKGLsSKekhFr7s4= +github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc= +github.com/go-openapi/jsonreference v0.21.3/go.mod h1:RqkUP0MrLf37HqxZxrIAtTWW4ZJIK1VzduhXYBEeGc4= +github.com/go-openapi/loads v0.23.2 h1:rJXAcP7g1+lWyBHC7iTY+WAF0rprtM+pm8Jxv1uQJp4= +github.com/go-openapi/loads v0.23.2/go.mod h1:IEVw1GfRt/P2Pplkelxzj9BYFajiWOtY2nHZNj4UnWY= +github.com/go-openapi/runtime v0.29.2 h1:UmwSGWNmWQqKm1c2MGgXVpC2FTGwPDQeUsBMufc5Yj0= +github.com/go-openapi/runtime v0.29.2/go.mod h1:biq5kJXRJKBJxTDJXAa00DOTa/anflQPhT0/wmjuy+0= +github.com/go-openapi/spec v0.22.1 h1:beZMa5AVQzRspNjvhe5aG1/XyBSMeX1eEOs7dMoXh/k= +github.com/go-openapi/spec v0.22.1/go.mod h1:c7aeIQT175dVowfp7FeCvXXnjN/MrpaONStibD2WtDA= +github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ= +github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8= github.com/go-openapi/swag v0.25.1 h1:6uwVsx+/OuvFVPqfQmOOPsqTcm5/GkBhNwLqIR916n8= github.com/go-openapi/swag v0.25.1/go.mod h1:bzONdGlT0fkStgGPd3bhZf1MnuPkf2YAys6h+jZipOo= github.com/go-openapi/swag/cmdutils v0.25.1 h1:nDke3nAFDArAa631aitksFGj2omusks88GF1VwdYqPY= @@ -91,8 +89,12 @@ github.com/go-openapi/swag/typeutils v0.25.1 h1:rD/9HsEQieewNt6/k+JBwkxuAHktFtH3 github.com/go-openapi/swag/typeutils v0.25.1/go.mod h1:9McMC/oCdS4BKwk2shEB7x17P6HmMmA6dQRtAkSnNb8= github.com/go-openapi/swag/yamlutils v0.25.1 h1:mry5ez8joJwzvMbaTGLhw8pXUnhDK91oSJLDPF1bmGk= github.com/go-openapi/swag/yamlutils v0.25.1/go.mod h1:cm9ywbzncy3y6uPm/97ysW8+wZ09qsks+9RS8fLWKqg= -github.com/go-openapi/validate v0.25.0 h1:JD9eGX81hDTjoY3WOzh6WqxVBVl7xjsLnvDo1GL5WPU= -github.com/go-openapi/validate v0.25.0/go.mod h1:SUY7vKrN5FiwK6LyvSwKjDfLNirSfWwHNgxd2l29Mmw= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= +github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= +github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= +github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= +github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw= +github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= @@ -241,8 +243,8 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= -go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= +go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.nhat.io/aferomock v0.8.0 h1:jESv25NuTpA/Wga+AOKqKI1lPKdYiBYvxpIUDJWyfPM= go.nhat.io/aferomock v0.8.0/go.mod h1:thJD/9Yeo+CcIW45u6rNU8WYc1yIWdqfOSpKcGtjAXw= go.nhat.io/grpcmock v0.33.0 h1:R9lfxT36n4ytmSJadIVXucpsORoGVLyUiQh2yxtpWZU= @@ -308,8 +310,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From fa2a24b8127c6658b8fd0a6d993819a0dd9381b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 12:56:08 +0200 Subject: [PATCH 215/300] CLOUD-727: Bump golang.org/x/crypto from 0.43.0 to 0.45.0 (#1366) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.43.0 to 0.45.0. - [Commits](https://github.com/golang/crypto/compare/v0.43.0...v0.45.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.45.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index fd929899fb..a3fcb18365 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.38.0 go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.43.0 + golang.org/x/crypto v0.45.0 google.golang.org/grpc v1.76.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.1 @@ -122,12 +122,12 @@ require ( go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.46.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/term v0.36.0 // indirect - golang.org/x/text v0.30.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.38.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 9f05daeab5..6d2d823fe4 100644 --- a/go.sum +++ b/go.sum @@ -289,8 +289,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -302,8 +302,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -320,18 +320,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 6cee6ddd8bd1b810f5adeb0a550037852ad93b56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 21:18:34 +0200 Subject: [PATCH 216/300] CLOUD-727: Bump k8s.io/apiextensions-apiserver from 0.34.1 to 0.34.2 (#1362) Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.34.1 to 0.34.2. - [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases) - [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.34.1...v0.34.2) --- updated-dependencies: - dependency-name: k8s.io/apiextensions-apiserver dependency-version: 0.34.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index a3fcb18365..23646d28df 100644 --- a/go.mod +++ b/go.mod @@ -32,10 +32,10 @@ require ( golang.org/x/crypto v0.45.0 google.golang.org/grpc v1.76.0 gotest.tools/v3 v3.5.2 - k8s.io/api v0.34.1 - k8s.io/apimachinery v0.34.1 - k8s.io/client-go v0.34.1 - k8s.io/component-base v0.34.1 + k8s.io/api v0.34.2 + k8s.io/apimachinery v0.34.2 + k8s.io/client-go v0.34.2 + k8s.io/component-base v0.34.2 sigs.k8s.io/controller-runtime v0.21.0 sigs.k8s.io/yaml v1.6.0 ) @@ -136,7 +136,7 @@ require ( google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.34.1 + k8s.io/apiextensions-apiserver v0.34.2 k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 diff --git a/go.sum b/go.sum index 6d2d823fe4..99974baa92 100644 --- a/go.sum +++ b/go.sum @@ -378,16 +378,16 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM= -k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk= -k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI= -k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc= -k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4= -k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY= -k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8= -k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A= -k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0= +k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= +k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= +k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo= +k8s.io/apiextensions-apiserver v0.34.2/go.mod h1:398CJrsgXF1wytdaanynDpJ67zG4Xq7yj91GrmYN2SE= +k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= +k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= +k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M= +k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE= +k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ= +k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= From 18d2f919165d871a50d2982a5b406319379c6564 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Sun, 30 Nov 2025 12:04:18 +0200 Subject: [PATCH 217/300] K8SPG-837 switch base image to RHEL 10 for PG K8s Operator (#1232) * K8SPG-837 switch base image to RHEL 10 for PG K8s Operator * use Snyk for CVE checks --- .github/workflows/scan.yml | 31 +++++++++++++----------------- build/postgres-operator/Dockerfile | 2 +- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 2302b172eb..b643595de2 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -30,16 +30,13 @@ jobs: export DOCKER_DEFAULT_PLATFORM='linux/arm64' make build-docker-image - - name: Run Trivy vulnerability scanner image (linux/arm64) - uses: aquasecurity/trivy-action@0.33.1 + - name: Run Snyk vulnerability scanner image (linux/arm64) + uses: snyk/actions/docker@master + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: - image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64' - format: 'table' - exit-code: '1' - ignore-unfixed: true - vuln-type: 'os,library' - severity: 'CRITICAL,HIGH' - version: 'v0.57.1' + image: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64' + args: --platform=linux/arm64 --severity-threshold=high --exclude-base-image-vulns --file=./build/postgres-operator/Dockerfile -fail-on=upgradable - name: Build an image from Dockerfile (linux/amd64) run: | @@ -49,13 +46,11 @@ jobs: export DOCKER_DEFAULT_PLATFORM='linux/amd64' make build-docker-image - - name: Run Trivy vulnerability scanner image (linux/amd64) - uses: aquasecurity/trivy-action@0.33.1 + - name: Run Snyk vulnerability scanner image (linux/amd64) + uses: snyk/actions/docker@master + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: - image-ref: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64' - format: 'table' - exit-code: '1' - ignore-unfixed: true - vuln-type: 'os,library' - severity: 'CRITICAL,HIGH' - version: 'v0.57.1' + image: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64' + args: --platform=linux/amd64 --severity-threshold=high --exclude-base-image-vulns --file=./build/postgres-operator/Dockerfile -fail-on=upgradable + diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index 6757f90686..59646d9aa4 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -45,7 +45,7 @@ RUN mkdir -p build/_output/bin \ RUN ./bin/license_aggregator.sh ./cmd/...; \ cp -r ./licenses /licenses -FROM registry.access.redhat.com/ubi9/ubi-minimal AS ubi9 +FROM registry.access.redhat.com/ubi10/ubi-minimal AS ubi10 RUN microdnf update -y && microdnf clean all -y LABEL name="Percona Postgres Operator" \ From 664152c4dfe98e8adb5b9dbfc8c893d7e6f0cd7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:10:40 +0200 Subject: [PATCH 218/300] CLOUD-727: Bump github.com/go-openapi/swag from 0.25.1 to 0.25.3 (#1358) Bumps [github.com/go-openapi/swag](https://github.com/go-openapi/swag) from 0.25.1 to 0.25.3. - [Commits](https://github.com/go-openapi/swag/compare/v0.25.1...v0.25.3) --- updated-dependencies: - dependency-name: github.com/go-openapi/swag dependency-version: 0.25.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 24 ++++++++++++------------ go.sum | 52 ++++++++++++++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index 23646d28df..4513ef1dc6 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/go-openapi/errors v0.22.4 github.com/go-openapi/runtime v0.29.2 github.com/go-openapi/strfmt v0.25.0 - github.com/go-openapi/swag v0.25.1 + github.com/go-openapi/swag v0.25.3 github.com/go-openapi/validate v0.25.1 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 @@ -46,17 +46,17 @@ require ( github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/go-openapi/swag/cmdutils v0.25.1 // indirect - github.com/go-openapi/swag/conv v0.25.1 // indirect - github.com/go-openapi/swag/fileutils v0.25.1 // indirect - github.com/go-openapi/swag/jsonname v0.25.1 // indirect - github.com/go-openapi/swag/jsonutils v0.25.1 // indirect - github.com/go-openapi/swag/loading v0.25.1 // indirect - github.com/go-openapi/swag/mangling v0.25.1 // indirect - github.com/go-openapi/swag/netutils v0.25.1 // indirect - github.com/go-openapi/swag/stringutils v0.25.1 // indirect - github.com/go-openapi/swag/typeutils v0.25.1 // indirect - github.com/go-openapi/swag/yamlutils v0.25.1 // indirect + github.com/go-openapi/swag/cmdutils v0.25.3 // indirect + github.com/go-openapi/swag/conv v0.25.3 // indirect + github.com/go-openapi/swag/fileutils v0.25.3 // indirect + github.com/go-openapi/swag/jsonname v0.25.3 // indirect + github.com/go-openapi/swag/jsonutils v0.25.3 // indirect + github.com/go-openapi/swag/loading v0.25.3 // indirect + github.com/go-openapi/swag/mangling v0.25.3 // indirect + github.com/go-openapi/swag/netutils v0.25.3 // indirect + github.com/go-openapi/swag/stringutils v0.25.3 // indirect + github.com/go-openapi/swag/typeutils v0.25.3 // indirect + github.com/go-openapi/swag/yamlutils v0.25.3 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/btree v1.1.3 // indirect diff --git a/go.sum b/go.sum index 99974baa92..26377a91e1 100644 --- a/go.sum +++ b/go.sum @@ -63,32 +63,32 @@ github.com/go-openapi/spec v0.22.1 h1:beZMa5AVQzRspNjvhe5aG1/XyBSMeX1eEOs7dMoXh/ github.com/go-openapi/spec v0.22.1/go.mod h1:c7aeIQT175dVowfp7FeCvXXnjN/MrpaONStibD2WtDA= github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ= github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8= -github.com/go-openapi/swag v0.25.1 h1:6uwVsx+/OuvFVPqfQmOOPsqTcm5/GkBhNwLqIR916n8= -github.com/go-openapi/swag v0.25.1/go.mod h1:bzONdGlT0fkStgGPd3bhZf1MnuPkf2YAys6h+jZipOo= -github.com/go-openapi/swag/cmdutils v0.25.1 h1:nDke3nAFDArAa631aitksFGj2omusks88GF1VwdYqPY= -github.com/go-openapi/swag/cmdutils v0.25.1/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= -github.com/go-openapi/swag/conv v0.25.1 h1:+9o8YUg6QuqqBM5X6rYL/p1dpWeZRhoIt9x7CCP+he0= -github.com/go-openapi/swag/conv v0.25.1/go.mod h1:Z1mFEGPfyIKPu0806khI3zF+/EUXde+fdeksUl2NiDs= -github.com/go-openapi/swag/fileutils v0.25.1 h1:rSRXapjQequt7kqalKXdcpIegIShhTPXx7yw0kek2uU= -github.com/go-openapi/swag/fileutils v0.25.1/go.mod h1:+NXtt5xNZZqmpIpjqcujqojGFek9/w55b3ecmOdtg8M= -github.com/go-openapi/swag/jsonname v0.25.1 h1:Sgx+qbwa4ej6AomWC6pEfXrA6uP2RkaNjA9BR8a1RJU= -github.com/go-openapi/swag/jsonname v0.25.1/go.mod h1:71Tekow6UOLBD3wS7XhdT98g5J5GR13NOTQ9/6Q11Zo= -github.com/go-openapi/swag/jsonutils v0.25.1 h1:AihLHaD0brrkJoMqEZOBNzTLnk81Kg9cWr+SPtxtgl8= -github.com/go-openapi/swag/jsonutils v0.25.1/go.mod h1:JpEkAjxQXpiaHmRO04N1zE4qbUEg3b7Udll7AMGTNOo= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1 h1:DSQGcdB6G0N9c/KhtpYc71PzzGEIc/fZ1no35x4/XBY= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.1/go.mod h1:kjmweouyPwRUEYMSrbAidoLMGeJ5p6zdHi9BgZiqmsg= -github.com/go-openapi/swag/loading v0.25.1 h1:6OruqzjWoJyanZOim58iG2vj934TysYVptyaoXS24kw= -github.com/go-openapi/swag/loading v0.25.1/go.mod h1:xoIe2EG32NOYYbqxvXgPzne989bWvSNoWoyQVWEZicc= -github.com/go-openapi/swag/mangling v0.25.1 h1:XzILnLzhZPZNtmxKaz/2xIGPQsBsvmCjrJOWGNz/ync= -github.com/go-openapi/swag/mangling v0.25.1/go.mod h1:CdiMQ6pnfAgyQGSOIYnZkXvqhnnwOn997uXZMAd/7mQ= -github.com/go-openapi/swag/netutils v0.25.1 h1:2wFLYahe40tDUHfKT1GRC4rfa5T1B4GWZ+msEFA4Fl4= -github.com/go-openapi/swag/netutils v0.25.1/go.mod h1:CAkkvqnUJX8NV96tNhEQvKz8SQo2KF0f7LleiJwIeRE= -github.com/go-openapi/swag/stringutils v0.25.1 h1:Xasqgjvk30eUe8VKdmyzKtjkVjeiXx1Iz0zDfMNpPbw= -github.com/go-openapi/swag/stringutils v0.25.1/go.mod h1:JLdSAq5169HaiDUbTvArA2yQxmgn4D6h4A+4HqVvAYg= -github.com/go-openapi/swag/typeutils v0.25.1 h1:rD/9HsEQieewNt6/k+JBwkxuAHktFtH3I3ysiFZqukA= -github.com/go-openapi/swag/typeutils v0.25.1/go.mod h1:9McMC/oCdS4BKwk2shEB7x17P6HmMmA6dQRtAkSnNb8= -github.com/go-openapi/swag/yamlutils v0.25.1 h1:mry5ez8joJwzvMbaTGLhw8pXUnhDK91oSJLDPF1bmGk= -github.com/go-openapi/swag/yamlutils v0.25.1/go.mod h1:cm9ywbzncy3y6uPm/97ysW8+wZ09qsks+9RS8fLWKqg= +github.com/go-openapi/swag v0.25.3 h1:FAa5wJXyDtI7yUztKDfZxDrSx+8WTg31MfCQ9s3PV+s= +github.com/go-openapi/swag v0.25.3/go.mod h1:tX9vI8Mj8Ny+uCEk39I1QADvIPI7lkndX4qCsEqhkS8= +github.com/go-openapi/swag/cmdutils v0.25.3 h1:EIwGxN143JCThNHnqfqs85R8lJcJG06qjJRZp3VvjLI= +github.com/go-openapi/swag/cmdutils v0.25.3/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.3 h1:PcB18wwfba7MN5BVlBIV+VxvUUeC2kEuCEyJ2/t2X7E= +github.com/go-openapi/swag/conv v0.25.3/go.mod h1:n4Ibfwhn8NJnPXNRhBO5Cqb9ez7alBR40JS4rbASUPU= +github.com/go-openapi/swag/fileutils v0.25.3 h1:P52Uhd7GShkeU/a1cBOuqIcHMHBrA54Z2t5fLlE85SQ= +github.com/go-openapi/swag/fileutils v0.25.3/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= +github.com/go-openapi/swag/jsonname v0.25.3 h1:U20VKDS74HiPaLV7UZkztpyVOw3JNVsit+w+gTXRj0A= +github.com/go-openapi/swag/jsonname v0.25.3/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= +github.com/go-openapi/swag/jsonutils v0.25.3 h1:kV7wer79KXUM4Ea4tBdAVTU842Rg6tWstX3QbM4fGdw= +github.com/go-openapi/swag/jsonutils v0.25.3/go.mod h1:ILcKqe4HC1VEZmJx51cVuZQ6MF8QvdfXsQfiaCs0z9o= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3 h1:/i3E9hBujtXfHy91rjtwJ7Fgv5TuDHgnSrYjhFxwxOw= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3/go.mod h1:8kYfCR2rHyOj25HVvxL5Nm8wkfzggddgjZm6RgjT8Ao= +github.com/go-openapi/swag/loading v0.25.3 h1:Nn65Zlzf4854MY6Ft0JdNrtnHh2bdcS/tXckpSnOb2Y= +github.com/go-openapi/swag/loading v0.25.3/go.mod h1:xajJ5P4Ang+cwM5gKFrHBgkEDWfLcsAKepIuzTmOb/c= +github.com/go-openapi/swag/mangling v0.25.3 h1:rGIrEzXaYWuUW1MkFmG3pcH+EIA0/CoUkQnIyB6TUyo= +github.com/go-openapi/swag/mangling v0.25.3/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= +github.com/go-openapi/swag/netutils v0.25.3 h1:XWXHZfL/65ABiv8rvGp9dtE0C6QHTYkCrNV77jTl358= +github.com/go-openapi/swag/netutils v0.25.3/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= +github.com/go-openapi/swag/stringutils v0.25.3 h1:nAmWq1fUTWl/XiaEPwALjp/8BPZJun70iDHRNq/sH6w= +github.com/go-openapi/swag/stringutils v0.25.3/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= +github.com/go-openapi/swag/typeutils v0.25.3 h1:2w4mEEo7DQt3V4veWMZw0yTPQibiL3ri2fdDV4t2TQc= +github.com/go-openapi/swag/typeutils v0.25.3/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= +github.com/go-openapi/swag/yamlutils v0.25.3 h1:LKTJjCn/W1ZfMec0XDL4Vxh8kyAnv1orH5F2OREDUrg= +github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao= github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= From a57867550380515098d00832229a996b52c8293d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:12:54 +0200 Subject: [PATCH 219/300] CLOUD-727: Bump golang.org/x/tools from 0.38.0 to 0.39.0 (#1361) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.38.0 to 0.39.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.38.0...v0.39.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.39.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 4513ef1dc6..823a179daf 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.29.0 // indirect + golang.org/x/mod v0.30.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect @@ -129,7 +129,7 @@ require ( golang.org/x/term v0.37.0 // indirect golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.38.0 + golang.org/x/tools v0.39.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect diff --git a/go.sum b/go.sum index 26377a91e1..56fa262b51 100644 --- a/go.sum +++ b/go.sum @@ -294,8 +294,8 @@ golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -339,8 +339,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 315dc1995e332e9ef11f28e029331ef24d0c441f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:14:58 +0200 Subject: [PATCH 220/300] CLOUD-727: Bump go.uber.org/zap from 1.27.0 to 1.27.1 (#1369) Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.27.0 to 1.27.1. - [Release notes](https://github.com/uber-go/zap/releases) - [Changelog](https://github.com/uber-go/zap/blob/master/CHANGELOG.md) - [Commits](https://github.com/uber-go/zap/compare/v1.27.0...v1.27.1) --- updated-dependencies: - dependency-name: go.uber.org/zap dependency-version: 1.27.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 823a179daf..83aa686adb 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 go.opentelemetry.io/otel/sdk v1.38.0 go.opentelemetry.io/otel/trace v1.38.0 - go.uber.org/zap v1.27.0 + go.uber.org/zap v1.27.1 golang.org/x/crypto v0.45.0 google.golang.org/grpc v1.76.0 gotest.tools/v3 v3.5.2 diff --git a/go.sum b/go.sum index 56fa262b51..96def5c566 100644 --- a/go.sum +++ b/go.sum @@ -279,8 +279,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= From 81ff846ae867be19ff8b87f79e0b87e7cfe398ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 16:17:05 +0200 Subject: [PATCH 221/300] CLOUD-727: Bump google.golang.org/grpc from 1.76.0 to 1.77.0 (#1359) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.76.0 to 1.77.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.76.0...v1.77.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.77.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 83aa686adb..c7736b5db3 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.1 golang.org/x/crypto v0.45.0 - google.golang.org/grpc v1.76.0 + google.golang.org/grpc v1.77.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.2 k8s.io/apimachinery v0.34.2 @@ -123,7 +123,7 @@ require ( go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.47.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/oauth2 v0.32.0 // indirect golang.org/x/sync v0.18.0 // indirect golang.org/x/sys v0.38.0 // indirect golang.org/x/term v0.37.0 // indirect @@ -131,7 +131,7 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.39.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 96def5c566..38001875e1 100644 --- a/go.sum +++ b/go.sum @@ -304,8 +304,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -349,12 +349,12 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 h1:8XJ4pajGwOlasW+L13MnEGA8W4115jJySQtVfS2/IBU= -google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4/go.mod h1:NnuHhy+bxcg30o7FnVAZbXsPHUDQ9qKWAQKCD7VxFtk= +google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= +google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= -google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= From 674c26a849fefde242e2d815c2e1efdd3b1d816b Mon Sep 17 00:00:00 2001 From: Michael Golowka <72365+pcman312@users.noreply.github.com> Date: Mon, 1 Dec 2025 01:42:43 -0700 Subject: [PATCH 222/300] Fix panic on JSON marshal if PITRestoreDateTime is not a pointer (#1368) Co-authored-by: Viacheslav Sarzhan --- .../v2/perconapgbackup_types.go | 2 +- .../v2/perconapgbackup_types_test.go | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go index 367b1d7f58..023a1b7fb9 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go @@ -129,7 +129,7 @@ func (t *PITRestoreDateTime) UnmarshalJSON(b []byte) (err error) { return nil } -func (t *PITRestoreDateTime) MarshalJSON() ([]byte, error) { +func (t PITRestoreDateTime) MarshalJSON() ([]byte, error) { if t.Time == nil { return []byte("null"), nil } diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go new file mode 100644 index 0000000000..e8b27d955c --- /dev/null +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go @@ -0,0 +1,69 @@ +package v2 + +import ( + "encoding/json" + "testing" + "time" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestPITRestoreDateTime_MarshalJSON(t *testing.T) { + type testCase struct { + data any + expected string + } + tests := map[string]testCase{ + "default": { + data: PITRestoreDateTime{}, + expected: `null`, + }, + "pointer": { + data: &PITRestoreDateTime{}, + expected: `null`, + }, + "nil pointer": { + data: (*PITRestoreDateTime)(nil), + expected: `null`, + }, + "non-pointer zero date time": { + data: PITRestoreDateTime{ + Time: ptr(metav1.NewTime(time.Time{})), + }, + expected: `"0001-01-01 00:00:00.000000+0000"`, + }, + "pointer zero date time": { + data: &PITRestoreDateTime{ + Time: ptr(metav1.NewTime(time.Time{})), + }, + expected: `"0001-01-01 00:00:00.000000+0000"`, + }, + "non-pointer with date time": { + data: PITRestoreDateTime{ + Time: ptr(metav1.NewTime(time.Date(2025, time.November, 21, 13, 14, 15, 345600000, time.UTC))), + }, + expected: `"2025-11-21 13:14:15.345600+0000"`, + }, + "pointer with date time": { + data: &PITRestoreDateTime{ + Time: ptr(metav1.NewTime(time.Date(2025, time.November, 21, 13, 14, 15, 345600000, time.UTC))), + }, + expected: `"2025-11-21 13:14:15.345600+0000"`, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + require.NotPanics(t, func() { + b, err := json.Marshal(test.data) + require.NoError(t, err) + require.JSONEq(t, test.expected, string(b)) + }) + }) + } +} + +func ptr[T any](v T) *T { + return &v +} From 1c8946f63d55e5c8131477047d5f411d90396842 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 10:43:34 +0200 Subject: [PATCH 223/300] CLOUD-727: Bump golangci/golangci-lint-action from 8 to 9 (#1371) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 8 to 9. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v8...v9) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- .github/workflows/reviewdog.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index a0a4a1e058..f97c846559 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -10,7 +10,7 @@ jobs: go-version: '^1.25.1' - uses: actions/checkout@v5 - name: golangci-lint - uses: golangci/golangci-lint-action@v8 + uses: golangci/golangci-lint-action@v9 with: version: latest only-new-issues: true From 14a76368d0067ff42401e648ccac4fb4043d4be1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 10:43:56 +0200 Subject: [PATCH 224/300] CLOUD-727: Bump actions/checkout from 5 to 6 (#1372) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- .github/workflows/reviewdog.yml | 16 ++++++++-------- .github/workflows/scan.yml | 2 +- .github/workflows/test.yml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index f97c846559..49c01a5f81 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -8,7 +8,7 @@ jobs: - uses: actions/setup-go@v6 with: go-version: '^1.25.1' - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: golangci-lint uses: golangci/golangci-lint-action@v9 with: @@ -20,7 +20,7 @@ jobs: name: runner / suggester / goimports-reviser runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: go-version: '^1.25.1' @@ -34,7 +34,7 @@ jobs: name: runner / suggester / gofmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - run: gofmt -w -s $(find . -not -path "*/vendor/*" -name "*.go") - uses: reviewdog/action-suggester@v1 with: @@ -44,7 +44,7 @@ jobs: name: runner / suggester / shfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: go-version: '^1.25.1' @@ -60,7 +60,7 @@ jobs: name: runner / shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: reviewdog/action-shellcheck@v1 with: github_token: ${{ secrets.github_token }} @@ -70,7 +70,7 @@ jobs: name: runner / misspell runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: reviewdog/action-misspell@v1 with: github_token: ${{ secrets.github_token }} @@ -81,7 +81,7 @@ jobs: name: runner / alex runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: reviewdog/action-alex@v1 with: github_token: ${{ secrets.github_token }} @@ -92,7 +92,7 @@ jobs: name: runner / manifests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: check on release branch if: ${{ contains(github.base_ref, 'release-') }} run: | diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index b643595de2..9e8f3274be 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index deeafa53f4..81054da730 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,12 +6,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone the code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup Go uses: actions/setup-go@v6 with: go-version: '^1.25.1' - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Basic tests run: make check - name: envtest From 5c84ff3e0dd6242ce8cc18b3aedecf95c084bb28 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Wed, 10 Dec 2025 12:12:49 +0200 Subject: [PATCH 225/300] K8SPG-852 add support of PG18 (#1370) * K8SPG-852 add support of PG18 * Use 1.6.6 and 1.6.7 custom ext versions * use default test images --------- Co-authored-by: Eleonora Zinchenko --- ...ator.crunchydata.com_postgresclusters.yaml | 4 +-- .../pgv2.percona.com_perconapgbackups.yaml | 2 +- .../pgv2.percona.com_perconapgclusters.yaml | 4 +-- .../pgv2.percona.com_perconapgrestores.yaml | 2 +- .../pgv2.percona.com_perconapgupgrades.yaml | 4 +-- .../pgv2.percona.com_perconapgclusters.yaml | 12 ++++---- ...crunchydata.com_crunchybridgeclusters.yaml | 6 ++-- ...res-operator.crunchydata.com_pgadmins.yaml | 2 +- ...s-operator.crunchydata.com_pgupgrades.yaml | 6 ++-- ...ator.crunchydata.com_postgresclusters.yaml | 4 +-- deploy/bundle.yaml | 30 +++++++++---------- deploy/crd.yaml | 30 +++++++++---------- deploy/cw-bundle.yaml | 30 +++++++++---------- .../custom-extensions/02-install-pg_cron.yaml | 2 +- .../custom-extensions/11-install-pg_cron.yaml | 2 +- .../custom-extensions/14-update-pg_cron.yaml | 2 +- e2e-tests/vars.sh | 3 +- hack/controller-generator.sh | 2 +- .../v2/perconapgcluster_types.go | 2 +- .../v2/perconapgupgrade_types.go | 2 +- .../v1beta1/crunchy_bridgecluster_types.go | 4 +-- .../v1beta1/pgupgrade_types.go | 4 +-- .../v1beta1/postgrescluster_types.go | 2 +- .../v1beta1/zz_generated.deepcopy.go | 4 +-- 24 files changed, 83 insertions(+), 82 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index f43983758c..02169bbf8a 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: postgresclusters.postgres-operator.crunchydata.com spec: group: postgres-operator.crunchydata.com @@ -17427,7 +17427,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml index 2961b92519..b3989160e7 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 893d1911a0..e89804051b 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -16859,7 +16859,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml index 2ff2df988a..0a0f2cc39f 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml index c861a27fd4..8418316924 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -2605,7 +2605,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 7fb6e89327..f807fa7e13 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -408,7 +408,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -17264,7 +17264,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -21810,7 +21810,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -21908,7 +21908,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -24510,7 +24510,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml index f93a59f512..cbbca84540 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml index 5820ff691c..86feaf6aff 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml index db71b1a270..ead8e93bc9 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -957,7 +957,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -2599,7 +2599,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 09005917b5..c7f7cedf8f 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -17369,7 +17369,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index fa440143fd..16d36f51b9 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com @@ -17561,7 +17561,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -22107,7 +22107,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22207,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com @@ -24811,7 +24811,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -25011,7 +25011,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27010,7 +27010,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27965,7 +27965,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -29607,7 +29607,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -29801,7 +29801,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -47168,7 +47168,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index b0bf292f26..9c12de3995 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com @@ -17561,7 +17561,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -22107,7 +22107,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22207,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com @@ -24811,7 +24811,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -25011,7 +25011,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27010,7 +27010,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27965,7 +27965,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -29607,7 +29607,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -29801,7 +29801,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -47168,7 +47168,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 5e19e282f1..2f66ce2184 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com @@ -17561,7 +17561,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -22107,7 +22107,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22207,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com @@ -24811,7 +24811,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -25011,7 +25011,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27010,7 +27010,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27965,7 +27965,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -29607,7 +29607,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -29801,7 +29801,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -47168,7 +47168,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml b/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml index 7d51929101..9f0fb7ccaf 100644 --- a/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml +++ b/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml @@ -6,7 +6,7 @@ spec: extensions: custom: - name: pg_cron - version: 1.6.1 + version: 1.6.6 patroni: dynamicConfiguration: postgresql: diff --git a/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml b/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml index 7d51929101..9f0fb7ccaf 100644 --- a/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml +++ b/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml @@ -6,7 +6,7 @@ spec: extensions: custom: - name: pg_cron - version: 1.6.1 + version: 1.6.6 patroni: dynamicConfiguration: postgresql: diff --git a/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml b/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml index f9092e2cdd..2099e58a74 100644 --- a/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml +++ b/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml @@ -6,7 +6,7 @@ spec: extensions: custom: - name: pg_cron - version: 1.6.4 + version: 1.6.7 patroni: dynamicConfiguration: postgresql: diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 6aaf2ce21b..76e9394aa2 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -27,8 +27,9 @@ if [[ ! $PG_VER && $IMAGE_POSTGRESQL ]]; then pg_version_value=$(echo "$IMAGE_POSTGRESQL" | sed -E 's/.*:(.*ppg)?([0-9]+).*/\2/') export PG_VER="${pg_version_value}" else - export PG_VER="${PG_VER:-17}" + export PG_VER="${PG_VER:-18}" fi + export IMAGE_PGBOUNCER=${IMAGE_PGBOUNCER:-"${IMAGE_BASE}:main-pgbouncer$PG_VER"} export IMAGE_POSTGRESQL=${IMAGE_POSTGRESQL:-"${IMAGE_BASE}:main-ppg$PG_VER-postgres"} export IMAGE_BACKREST=${IMAGE_BACKREST:-"${IMAGE_BASE}:main-pgbackrest$PG_VER"} diff --git a/hack/controller-generator.sh b/hack/controller-generator.sh index 6a7b603f25..0c492c3a1b 100755 --- a/hack/controller-generator.sh +++ b/hack/controller-generator.sh @@ -22,6 +22,6 @@ set -eu # Find `controller-gen` on the current PATH or install it to the Go install path. tool="$(command -v controller-gen || true)" [ -n "$tool" ] || tool="$GOBIN/controller-gen" -[ -x "$tool" ] || go install 'sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.5' +[ -x "$tool" ] || go install 'sigs.k8s.io/controller-tools/cmd/controller-gen@v0.18.0' "$tool" "$@" diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index c950927e7d..77d4789b78 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -95,7 +95,7 @@ type PerconaPGClusterSpec struct { // The major version of PostgreSQL installed in the PostgreSQL image // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=12 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 // +operator-sdk:csv:customresourcedefinitions:type=spec PostgresVersion int `json:"postgresVersion"` diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go index 70943c4dc9..5b5797627e 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go @@ -65,7 +65,7 @@ type PerconaPGUpgradeSpec struct { // The major version of PostgreSQL to be upgraded to. // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=13 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 ToPostgresVersion int `json:"toPostgresVersion"` // The image to use for PostgreSQL containers after upgrade. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go index 39342012c3..fb637df94c 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go @@ -45,10 +45,10 @@ type CrunchyBridgeClusterSpec struct { Plan string `json:"plan"` // The ID of the cluster's major Postgres version. - // Currently Bridge offers 13-17 + // Currently Bridge offers 13-18 // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=13 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 // +operator-sdk:csv:customresourcedefinitions:type=spec,order=1 PostgresVersion int `json:"majorVersion"` diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go index 823a793174..49e7796706 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go @@ -48,7 +48,7 @@ type PGUpgradeSpec struct { // The major version of PostgreSQL before the upgrade. // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=12 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 FromPostgresVersion int `json:"fromPostgresVersion"` // TODO(benjaminjb): define webhook validation to make sure @@ -59,7 +59,7 @@ type PGUpgradeSpec struct { // The major version of PostgreSQL to be upgraded to. // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=13 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 ToPostgresVersion int `json:"toPostgresVersion"` // The image name to use for PostgreSQL containers after upgrade. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index e2a846ceb0..7ab7fa7894 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -129,7 +129,7 @@ type PostgresClusterSpec struct { // The major version of PostgreSQL installed in the PostgreSQL image // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=12 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 // +operator-sdk:csv:customresourcedefinitions:type=spec,order=1 PostgresVersion int `json:"postgresVersion"` diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 2ef09eb950..a6a28892fe 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -2394,12 +2394,12 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { } if in.InternalTrafficPolicy != nil { in, out := &in.InternalTrafficPolicy, &out.InternalTrafficPolicy - *out = new(corev1.ServiceInternalTrafficPolicy) + *out = new(corev1.ServiceInternalTrafficPolicyType) **out = **in } if in.ExternalTrafficPolicy != nil { in, out := &in.ExternalTrafficPolicy, &out.ExternalTrafficPolicy - *out = new(corev1.ServiceExternalTrafficPolicy) + *out = new(corev1.ServiceExternalTrafficPolicyType) **out = **in } } From c3e7cb346e62c3ab869287a063f0296c2663c3f3 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Wed, 10 Dec 2025 12:12:49 +0200 Subject: [PATCH 226/300] K8SPG-852 add support of PG18 (#1370) * K8SPG-852 add support of PG18 * Use 1.6.6 and 1.6.7 custom ext versions * use default test images --------- Co-authored-by: Eleonora Zinchenko --- ...ator.crunchydata.com_postgresclusters.yaml | 4 +-- .../pgv2.percona.com_perconapgbackups.yaml | 2 +- .../pgv2.percona.com_perconapgclusters.yaml | 4 +-- .../pgv2.percona.com_perconapgrestores.yaml | 2 +- .../pgv2.percona.com_perconapgupgrades.yaml | 4 +-- .../pgv2.percona.com_perconapgclusters.yaml | 12 ++++---- ...crunchydata.com_crunchybridgeclusters.yaml | 6 ++-- ...res-operator.crunchydata.com_pgadmins.yaml | 2 +- ...s-operator.crunchydata.com_pgupgrades.yaml | 6 ++-- ...ator.crunchydata.com_postgresclusters.yaml | 4 +-- deploy/bundle.yaml | 30 +++++++++---------- deploy/crd.yaml | 30 +++++++++---------- deploy/cw-bundle.yaml | 30 +++++++++---------- .../custom-extensions/02-install-pg_cron.yaml | 2 +- .../custom-extensions/11-install-pg_cron.yaml | 2 +- .../custom-extensions/14-update-pg_cron.yaml | 2 +- e2e-tests/vars.sh | 3 +- hack/controller-generator.sh | 2 +- .../v2/perconapgcluster_types.go | 2 +- .../v2/perconapgupgrade_types.go | 2 +- .../v1beta1/crunchy_bridgecluster_types.go | 4 +-- .../v1beta1/pgupgrade_types.go | 4 +-- .../v1beta1/postgrescluster_types.go | 2 +- .../v1beta1/zz_generated.deepcopy.go | 4 +-- 24 files changed, 83 insertions(+), 82 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index f43983758c..02169bbf8a 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: postgresclusters.postgres-operator.crunchydata.com spec: group: postgres-operator.crunchydata.com @@ -17427,7 +17427,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml index 2961b92519..b3989160e7 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 893d1911a0..e89804051b 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -16859,7 +16859,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml index 2ff2df988a..0a0f2cc39f 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml index c861a27fd4..8418316924 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -2605,7 +2605,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 7fb6e89327..f807fa7e13 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -408,7 +408,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -17264,7 +17264,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -21810,7 +21810,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -21908,7 +21908,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -24510,7 +24510,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml index f93a59f512..cbbca84540 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml index 5820ff691c..86feaf6aff 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml index db71b1a270..ead8e93bc9 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -957,7 +957,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -2599,7 +2599,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 09005917b5..c7f7cedf8f 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -17369,7 +17369,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 020076242b..4f1d32f4b2 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgbackups.pgv2.percona.com @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgclusters.pgv2.percona.com @@ -17561,7 +17561,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -22107,7 +22107,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22207,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgupgrades.pgv2.percona.com @@ -24811,7 +24811,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -25011,7 +25011,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27010,7 +27010,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27965,7 +27965,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -29607,7 +29607,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -29801,7 +29801,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -47168,7 +47168,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index be4cee1441..c45ab9a88a 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgbackups.pgv2.percona.com @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgclusters.pgv2.percona.com @@ -17561,7 +17561,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -22107,7 +22107,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22207,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgupgrades.pgv2.percona.com @@ -24811,7 +24811,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -25011,7 +25011,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27010,7 +27010,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27965,7 +27965,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -29607,7 +29607,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -29801,7 +29801,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -47168,7 +47168,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 3fc6cc1c48..f05250307f 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -64,8 +64,8 @@ spec: majorVersion: description: |- The ID of the cluster's major Postgres version. - Currently Bridge offers 13-17 - maximum: 17 + Currently Bridge offers 13-18 + maximum: 18 minimum: 13 type: integer metadata: @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgbackups.pgv2.percona.com @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgclusters.pgv2.percona.com @@ -17561,7 +17561,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: @@ -22107,7 +22107,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22207,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: pgv2.percona.com/version: v2.8.0 name: perconapgupgrades.pgv2.percona.com @@ -24811,7 +24811,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -25011,7 +25011,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27010,7 +27010,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -27965,7 +27965,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 17 + maximum: 18 minimum: 12 type: integer image: @@ -29607,7 +29607,7 @@ spec: type: string toPostgresVersion: description: The major version of PostgreSQL to be upgraded to. - maximum: 17 + maximum: 18 minimum: 13 type: integer tolerations: @@ -29801,7 +29801,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.5 + controller-gen.kubebuilder.io/version: v0.18.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -47168,7 +47168,7 @@ spec: postgresVersion: description: The major version of PostgreSQL installed in the PostgreSQL image - maximum: 17 + maximum: 18 minimum: 12 type: integer proxy: diff --git a/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml b/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml index 7d51929101..9f0fb7ccaf 100644 --- a/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml +++ b/e2e-tests/tests/custom-extensions/02-install-pg_cron.yaml @@ -6,7 +6,7 @@ spec: extensions: custom: - name: pg_cron - version: 1.6.1 + version: 1.6.6 patroni: dynamicConfiguration: postgresql: diff --git a/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml b/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml index 7d51929101..9f0fb7ccaf 100644 --- a/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml +++ b/e2e-tests/tests/custom-extensions/11-install-pg_cron.yaml @@ -6,7 +6,7 @@ spec: extensions: custom: - name: pg_cron - version: 1.6.1 + version: 1.6.6 patroni: dynamicConfiguration: postgresql: diff --git a/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml b/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml index f9092e2cdd..2099e58a74 100644 --- a/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml +++ b/e2e-tests/tests/custom-extensions/14-update-pg_cron.yaml @@ -6,7 +6,7 @@ spec: extensions: custom: - name: pg_cron - version: 1.6.4 + version: 1.6.7 patroni: dynamicConfiguration: postgresql: diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 42691936e0..10a7606c90 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -27,8 +27,9 @@ if [[ ! $PG_VER && $IMAGE_POSTGRESQL ]]; then pg_version_value=$(echo "$IMAGE_POSTGRESQL" | sed -E 's/.*:(.*ppg)?([0-9]+).*/\2/') export PG_VER="${pg_version_value}" else - export PG_VER="${PG_VER:-17}" + export PG_VER="${PG_VER:-18}" fi + export IMAGE_PGBOUNCER=${IMAGE_PGBOUNCER:-"${IMAGE_BASE}:main-pgbouncer$PG_VER"} export IMAGE_POSTGRESQL=${IMAGE_POSTGRESQL:-"perconalab/percona-distribution-postgresql:$PG_VER"} export IMAGE_BACKREST=${IMAGE_BACKREST:-"${IMAGE_BASE}:main-pgbackrest$PG_VER"} diff --git a/hack/controller-generator.sh b/hack/controller-generator.sh index 6a7b603f25..0c492c3a1b 100755 --- a/hack/controller-generator.sh +++ b/hack/controller-generator.sh @@ -22,6 +22,6 @@ set -eu # Find `controller-gen` on the current PATH or install it to the Go install path. tool="$(command -v controller-gen || true)" [ -n "$tool" ] || tool="$GOBIN/controller-gen" -[ -x "$tool" ] || go install 'sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.5' +[ -x "$tool" ] || go install 'sigs.k8s.io/controller-tools/cmd/controller-gen@v0.18.0' "$tool" "$@" diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index c950927e7d..77d4789b78 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -95,7 +95,7 @@ type PerconaPGClusterSpec struct { // The major version of PostgreSQL installed in the PostgreSQL image // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=12 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 // +operator-sdk:csv:customresourcedefinitions:type=spec PostgresVersion int `json:"postgresVersion"` diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go index 70943c4dc9..5b5797627e 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go @@ -65,7 +65,7 @@ type PerconaPGUpgradeSpec struct { // The major version of PostgreSQL to be upgraded to. // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=13 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 ToPostgresVersion int `json:"toPostgresVersion"` // The image to use for PostgreSQL containers after upgrade. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go index 39342012c3..fb637df94c 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/crunchy_bridgecluster_types.go @@ -45,10 +45,10 @@ type CrunchyBridgeClusterSpec struct { Plan string `json:"plan"` // The ID of the cluster's major Postgres version. - // Currently Bridge offers 13-17 + // Currently Bridge offers 13-18 // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=13 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 // +operator-sdk:csv:customresourcedefinitions:type=spec,order=1 PostgresVersion int `json:"majorVersion"` diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go index 823a793174..49e7796706 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgupgrade_types.go @@ -48,7 +48,7 @@ type PGUpgradeSpec struct { // The major version of PostgreSQL before the upgrade. // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=12 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 FromPostgresVersion int `json:"fromPostgresVersion"` // TODO(benjaminjb): define webhook validation to make sure @@ -59,7 +59,7 @@ type PGUpgradeSpec struct { // The major version of PostgreSQL to be upgraded to. // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=13 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 ToPostgresVersion int `json:"toPostgresVersion"` // The image name to use for PostgreSQL containers after upgrade. diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index e2a846ceb0..7ab7fa7894 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -129,7 +129,7 @@ type PostgresClusterSpec struct { // The major version of PostgreSQL installed in the PostgreSQL image // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=12 - // +kubebuilder:validation:Maximum=17 + // +kubebuilder:validation:Maximum=18 // +operator-sdk:csv:customresourcedefinitions:type=spec,order=1 PostgresVersion int `json:"postgresVersion"` diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 2ef09eb950..a6a28892fe 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -2394,12 +2394,12 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { } if in.InternalTrafficPolicy != nil { in, out := &in.InternalTrafficPolicy, &out.InternalTrafficPolicy - *out = new(corev1.ServiceInternalTrafficPolicy) + *out = new(corev1.ServiceInternalTrafficPolicyType) **out = **in } if in.ExternalTrafficPolicy != nil { in, out := &in.ExternalTrafficPolicy, &out.ExternalTrafficPolicy - *out = new(corev1.ServiceExternalTrafficPolicy) + *out = new(corev1.ServiceExternalTrafficPolicyType) **out = **in } } From 18fb2bcaf02d34c65beea73e20b05bb4e08912a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 12:56:08 +0200 Subject: [PATCH 227/300] CLOUD-727: Bump golang.org/x/crypto from 0.43.0 to 0.45.0 (#1366) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.43.0 to 0.45.0. - [Commits](https://github.com/golang/crypto/compare/v0.43.0...v0.45.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.45.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 9561d75171..9fb0c74cb4 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.38.0 go.opentelemetry.io/otel/trace v1.38.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.43.0 + golang.org/x/crypto v0.45.0 google.golang.org/grpc v1.76.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.1 @@ -123,12 +123,12 @@ require ( go.opentelemetry.io/otel/metric v1.38.0 // indirect go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.46.0 // indirect + golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/term v0.36.0 // indirect - golang.org/x/text v0.30.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.38.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 07a898ce09..dd2b3c3cda 100644 --- a/go.sum +++ b/go.sum @@ -287,8 +287,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -300,8 +300,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -318,18 +318,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 3a5ef6238798c0ebedd222cb7179f1da39e2f02e Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Wed, 10 Dec 2025 15:52:30 +0200 Subject: [PATCH 228/300] Go tidy for fa2a24b81 --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index dd2b3c3cda..59497a917f 100644 --- a/go.sum +++ b/go.sum @@ -308,8 +308,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From c5338ba41bb39c2435e08d87baa972529aabef94 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Wed, 10 Dec 2025 16:55:46 +0200 Subject: [PATCH 229/300] K8SPG-913: Update versions for 2.8.1 release --- config/bundle/kustomization.yaml | 2 +- .../versionlabel_in_perconapgbackups.yaml | 2 +- .../versionlabel_in_perconapgclusters.yaml | 2 +- .../versionlabel_in_perconapgrestores.yaml | 2 +- .../versionlabel_in_perconapgupgrade.yaml | 2 +- config/cw-bundle/kustomization.yaml | 2 +- config/manager/cluster/kustomization.yaml | 2 +- config/manager/namespace/kustomization.yaml | 2 +- deploy/bundle.yaml | 10 ++-- deploy/cr.yaml | 18 +++---- deploy/crd.yaml | 8 +-- deploy/cw-bundle.yaml | 10 ++-- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 +-- e2e-tests/release_versions | 53 ++++++++++--------- e2e-tests/tests/init-deploy/05-assert.yaml | 12 ++--- .../tests/upgrade-consistency/03-assert.yaml | 2 +- .../upgrade-consistency/03-patch-cluster.yaml | 2 +- e2e-tests/vars.sh | 2 +- percona/version/version.txt | 2 +- 21 files changed, 76 insertions(+), 71 deletions(-) diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index 0412fd1ddd..351b02520f 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -7,4 +7,4 @@ resources: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newTag: 2.8.1 diff --git a/config/crd/patches/versionlabel_in_perconapgbackups.yaml b/config/crd/patches/versionlabel_in_perconapgbackups.yaml index d4c5958860..771acd9abe 100644 --- a/config/crd/patches/versionlabel_in_perconapgbackups.yaml +++ b/config/crd/patches/versionlabel_in_perconapgbackups.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgbackups.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 diff --git a/config/crd/patches/versionlabel_in_perconapgclusters.yaml b/config/crd/patches/versionlabel_in_perconapgclusters.yaml index 9ee2cce213..2779a808a2 100644 --- a/config/crd/patches/versionlabel_in_perconapgclusters.yaml +++ b/config/crd/patches/versionlabel_in_perconapgclusters.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgclusters.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 diff --git a/config/crd/patches/versionlabel_in_perconapgrestores.yaml b/config/crd/patches/versionlabel_in_perconapgrestores.yaml index 9d4796443f..29161c8d9c 100644 --- a/config/crd/patches/versionlabel_in_perconapgrestores.yaml +++ b/config/crd/patches/versionlabel_in_perconapgrestores.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgrestores.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 diff --git a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml index 75d0fce2bb..17b3ed4c15 100644 --- a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml +++ b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgupgrades.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 0b3c810eab..50d3be43b0 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -8,4 +8,4 @@ resources: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newTag: 2.8.1 diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index 940a80d27b..da7695bf97 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -9,4 +9,4 @@ patchesStrategicMerge: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newTag: 2.8.1 diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 1e4cfc0e67..5e3b2e7dab 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -10,4 +10,4 @@ patchesStrategicMerge: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.0 + newTag: 2.8.1 diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 4f1d32f4b2..4bfabc4df2 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53964,7 +53964,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/percona/percona-postgresql-operator:2.8.1 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index ed3064d5d1..ab2e5baf80 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,9 +9,9 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: 2.8.0 + crVersion: 2.8.1 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/percona/percona-postgresql-operator:2.8.1 # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: docker.io/percona/percona-distribution-postgresql:17.6-1 + image: docker.io/percona/percona-distribution-postgresql:17.7-1 imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -188,7 +188,7 @@ spec: # - secretRef: # name: instance-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/percona/percona-postgresql-operator:2.8.1 # resources: # limits: # cpu: 2.0 @@ -312,7 +312,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: docker.io/percona/percona-pgbouncer:1.24.1-1 + image: docker.io/percona/percona-pgbouncer:1.25.0-1 # env: # - name: MY_ENV # value: "1000" @@ -409,7 +409,7 @@ spec: pgbackrest: # metadata: # labels: - image: docker.io/percona/percona-pgbackrest:2.56.0-1 + image: docker.io/percona/percona-pgbackrest:2.57.0-1 # env: # - name: MY_ENV # value: "1000" @@ -417,7 +417,7 @@ spec: # - secretRef: # name: repo-host-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/percona/percona-postgresql-operator:2.8.1 # resources: # limits: # cpu: 2.0 @@ -613,7 +613,7 @@ spec: pmm: enabled: false - image: docker.io/percona/pmm-client:3.4.1 + image: docker.io/percona/pmm-client:3.5.0 # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -647,7 +647,7 @@ spec: # - basebackup # extensions: -# image: docker.io/percona/percona-postgresql-operator:2.8.0 +# image: docker.io/percona/percona-postgresql-operator:2.8.1 # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/crd.yaml b/deploy/crd.yaml index c45ab9a88a..c616f88163 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index f05250307f..66dfcf83b3 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.0 + pgv2.percona.com/version: v2.8.1 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53962,7 +53962,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/percona/percona-postgresql-operator:2.8.1 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 1abc72e4c5..d9869a9849 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/percona/percona-postgresql-operator:2.8.1 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 7da02aca8d..e00b14a588 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.0 + image: docker.io/percona/percona-postgresql-operator:2.8.1 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 2a28427a41..b685fc5f2f 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: docker.io/percona/percona-postgresql-operator:2.8.0-upgrade + image: docker.io/percona/percona-postgresql-operator:2.8.1-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.6-1 - toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.24.1-1 - toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.56.0-1 + toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.7-1 + toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.25.0-1 + toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.57.0-1 diff --git a/e2e-tests/release_versions b/e2e-tests/release_versions index a425622447..5b0bc10bc7 100644 --- a/e2e-tests/release_versions +++ b/e2e-tests/release_versions @@ -1,37 +1,42 @@ # Images versions -IMAGE_OPERATOR=percona/percona-postgresql-operator:2.8.0 +IMAGE_OPERATOR=percona/percona-postgresql-operator:2.8.1 -IMAGE_POSTGRESQL17=percona/percona-distribution-postgresql:17.6-1 -IMAGE_PGBOUNCER17=percona/percona-pgbouncer:1.24.1-1 -IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.8.0-ppg17.6-postgres-gis3.3.8 -IMAGE_BACKREST17=percona/percona-pgbackrest:2.56.0-1 +IMAGE_POSTGRESQL18=percona/percona-distribution-postgresql:18.1-1 +IMAGE_PGBOUNCER18=percona/percona-pgbouncer:1.25.0-1 +IMAGE_POSTGIS18=percona/percona-postgresql-operator:2.8.1-ppg18.1-postgres-gis3.5.4 +IMAGE_BACKREST18=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL16=percona/percona-distribution-postgresql:16.10-1 -IMAGE_PGBOUNCER16=percona/percona-pgbouncer:1.24.1-1 -IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.8.0-ppg16.10-postgres-gis3.3.8 -IMAGE_BACKREST16=percona/percona-pgbackrest:2.56.0-1 +IMAGE_POSTGRESQL17=percona/percona-distribution-postgresql:17.7-1 +IMAGE_PGBOUNCER17=percona/percona-pgbouncer:1.25.0-1 +IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.8.1-ppg17.7-postgres-gis3.3.8 +IMAGE_BACKREST17=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL15=percona/percona-distribution-postgresql:15.14-1 -IMAGE_PGBOUNCER15=percona/percona-pgbouncer:1.24.1-1 -IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.8.0-ppg15.14-postgres-gis3.3.8 -IMAGE_BACKREST15=percona/percona-pgbackrest:2.56.0-1 +IMAGE_POSTGRESQL16=percona/percona-distribution-postgresql:16.11-1 +IMAGE_PGBOUNCER16=percona/percona-pgbouncer:1.25.0-1 +IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.8.1-ppg16.11-postgres-gis3.3.8 +IMAGE_BACKREST16=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL14=percona/percona-distribution-postgresql:14.19-1 -IMAGE_PGBOUNCER14=percona/percona-pgbouncer:1.24.1-1 -IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.8.0-ppg14.19-postgres-gis3.3.8 -IMAGE_BACKREST14=percona/percona-pgbackrest:2.56.0-1 +IMAGE_POSTGRESQL15=percona/percona-distribution-postgresql:15.15-1 +IMAGE_PGBOUNCER15=percona/percona-pgbouncer:1.25.0-1 +IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.8.1-ppg15.15-postgres-gis3.3.8 +IMAGE_BACKREST15=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL13=percona/percona-distribution-postgresql:13.22-1 -IMAGE_PGBOUNCER13=percona/percona-pgbouncer:1.24.1-1 -IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.8.0-ppg13.22-postgres-gis3.3.8 -IMAGE_BACKREST13=percona/percona-pgbackrest:2.56.0-1 +IMAGE_POSTGRESQL14=percona/percona-distribution-postgresql:14.20-1 +IMAGE_PGBOUNCER14=percona/percona-pgbouncer:1.25.0-1 +IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.8.1-ppg14.20-postgres-gis3.3.8 +IMAGE_BACKREST14=percona/percona-pgbackrest:2.57.0-1 -IMAGE_UPGRADE=percona/percona-postgresql-operator:2.8.0-upgrade +IMAGE_POSTGRESQL13=percona/percona-distribution-postgresql:13.23-1 +IMAGE_PGBOUNCER13=percona/percona-pgbouncer:1.25.0-1 +IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.8.1-ppg13.23-postgres-gis3.3.8 +IMAGE_BACKREST13=percona/percona-pgbackrest:2.57.0-1 + +IMAGE_UPGRADE=percona/percona-postgresql-operator:2.8.1-upgrade IMAGE_PMM_CLIENT=percona/pmm-client:2.44.1-1 IMAGE_PMM_SERVER=percona/pmm-server:2.44.1 -IMAGE_PMM3_CLIENT=percona/pmm-client:3.4.1 -IMAGE_PMM3_SERVER=percona/pmm-server:3.4.1 +IMAGE_PMM3_CLIENT=percona/pmm-client:3.5.0 +IMAGE_PMM3_SERVER=percona/pmm-server:3.5.0 # Supported k8s versions GKE_MIN=1.31 diff --git a/e2e-tests/tests/init-deploy/05-assert.yaml b/e2e-tests/tests/init-deploy/05-assert.yaml index 246ab59daf..751bfddb26 100644 --- a/e2e-tests/tests/init-deploy/05-assert.yaml +++ b/e2e-tests/tests/init-deploy/05-assert.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.8.1 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -81,7 +81,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.8.1 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -144,7 +144,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.8.1 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -168,7 +168,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.8.1 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -191,7 +191,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.8.1 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" @@ -214,7 +214,7 @@ spec: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.0 + pgv2.percona.com/version: 2.8.1 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" diff --git a/e2e-tests/tests/upgrade-consistency/03-assert.yaml b/e2e-tests/tests/upgrade-consistency/03-assert.yaml index bcc9f45111..4a92c0a70a 100644 --- a/e2e-tests/tests/upgrade-consistency/03-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.8.0 + crVersion: 2.8.1 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 959d3aab14..6b1149993c 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.8.0" + cr_version="2.8.1" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ diff --git a/e2e-tests/vars.sh b/e2e-tests/vars.sh index 10a7606c90..2deb3360c3 100755 --- a/e2e-tests/vars.sh +++ b/e2e-tests/vars.sh @@ -27,7 +27,7 @@ if [[ ! $PG_VER && $IMAGE_POSTGRESQL ]]; then pg_version_value=$(echo "$IMAGE_POSTGRESQL" | sed -E 's/.*:(.*ppg)?([0-9]+).*/\2/') export PG_VER="${pg_version_value}" else - export PG_VER="${PG_VER:-18}" + export PG_VER="${PG_VER:-17}" fi export IMAGE_PGBOUNCER=${IMAGE_PGBOUNCER:-"${IMAGE_BASE}:main-pgbouncer$PG_VER"} diff --git a/percona/version/version.txt b/percona/version/version.txt index 834f262953..dbe5900654 100644 --- a/percona/version/version.txt +++ b/percona/version/version.txt @@ -1 +1 @@ -2.8.0 +2.8.1 From 85ed95db1234d94b20cc993a9c69d9c0b3a3b1ea Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Fri, 12 Dec 2025 09:56:46 +0200 Subject: [PATCH 230/300] K8SPG-913: increase custom-tls timeout --- e2e-tests/tests/custom-tls/09-assert.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/custom-tls/09-assert.yaml b/e2e-tests/tests/custom-tls/09-assert.yaml index 2a7385a451..6f4cc49b2e 100644 --- a/e2e-tests/tests/custom-tls/09-assert.yaml +++ b/e2e-tests/tests/custom-tls/09-assert.yaml @@ -1,6 +1,6 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 100 +timeout: 160 --- kind: StatefulSet apiVersion: apps/v1 From 06758b96e3ea4f6e87ce7d59bc503f600ecd2244 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Mon, 15 Dec 2025 16:10:33 +0200 Subject: [PATCH 231/300] K8SPG-913: allow PG17 in fromPostgresVersion --- deploy/crd.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/crd.yaml b/deploy/crd.yaml index c616f88163..3c278b8a58 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -23160,7 +23160,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 16 + maximum: 17 minimum: 12 type: integer image: From d86c8fa52323d6ca69f46fd67ec5d95d8a2d561f Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Tue, 16 Dec 2025 14:27:13 +0200 Subject: [PATCH 232/300] Revert images back to main after 2.8.1 release --- Makefile | 9 +++++++-- config/bundle/kustomization.yaml | 2 +- .../versionlabel_in_perconapgbackups.yaml | 2 +- .../versionlabel_in_perconapgclusters.yaml | 2 +- .../versionlabel_in_perconapgrestores.yaml | 2 +- .../versionlabel_in_perconapgupgrade.yaml | 2 +- config/cw-bundle/kustomization.yaml | 2 +- config/manager/cluster/kustomization.yaml | 2 +- config/manager/namespace/kustomization.yaml | 2 +- deploy/bundle.yaml | 10 +++++----- deploy/cr.yaml | 18 +++++++++--------- deploy/crd.yaml | 8 ++++---- deploy/cw-bundle.yaml | 10 +++++----- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 ++++---- e2e-tests/tests/init-deploy/05-assert.yaml | 12 ++++++------ .../tests/upgrade-consistency/01-assert.yaml | 2 +- .../upgrade-consistency/01-create-cluster.yaml | 2 +- .../tests/upgrade-consistency/02-assert.yaml | 2 +- .../upgrade-consistency/02-patch-cluster.yaml | 2 +- .../tests/upgrade-consistency/03-assert.yaml | 2 +- .../upgrade-consistency/03-patch-cluster.yaml | 2 +- .../testdata/sidecar-resources-cr.yaml | 2 +- percona/version/version.txt | 2 +- 25 files changed, 58 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 528b983dbb..72854a544f 100644 --- a/Makefile +++ b/Makefile @@ -443,6 +443,9 @@ rm -rf $$TMP_DIR ;\ } endef +update-version: + echo $(NEXT_VER) > percona/version/version.txt + # Prepare release PG_VER ?= $(shell grep -o "postgresVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+") include e2e-tests/release_versions @@ -469,11 +472,11 @@ MINOR_VER := $(word 2,$(subst ., ,$(CURRENT_VERSION))) NEXT_VER := $(MAJOR_VER).$(shell expr $(MINOR_VER) + 1).0 PREV1_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 1).0 PREV2_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 2).0 -after-release: generate - echo $(NEXT_VER) > percona/version/version.txt +after-release: update-version generate $(SED) -i \ -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(NEXT_VER)/}" \ -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ + -e "/initContainer:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" \ -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ @@ -484,6 +487,8 @@ after-release: generate -e "/^spec:/,/^ toPostgresImage:/{s#toPostgresImage: .*#toPostgresImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ -e "/^spec:/,/^ toPgBouncerImage:/{s#toPgBouncerImage: .*#toPgBouncerImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ -e "/^spec:/,/^ toPgBackRestImage:/{s#toPgBackRestImage: .*#toPgBackRestImage: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" deploy/upgrade.yaml + +# Update upgrade-consistency $(SED) -i "s/$(PREV2_VERSION)/$(PREV1_VERSION)/g" e2e-tests/tests/upgrade-consistency/01-*.yaml $(SED) -i "s/$(PREV1_VERSION)/$(CURRENT_VERSION)/g" e2e-tests/tests/upgrade-consistency/02-*.yaml $(SED) -i "s/$(CURRENT_VERSION)/$(NEXT_VER)/g" e2e-tests/tests/upgrade-consistency/03-*.yaml e2e-tests/tests/init-deploy/05-assert.yaml \ No newline at end of file diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index 351b02520f..12eb42b5da 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -7,4 +7,4 @@ resources: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: main diff --git a/config/crd/patches/versionlabel_in_perconapgbackups.yaml b/config/crd/patches/versionlabel_in_perconapgbackups.yaml index 771acd9abe..3c32866138 100644 --- a/config/crd/patches/versionlabel_in_perconapgbackups.yaml +++ b/config/crd/patches/versionlabel_in_perconapgbackups.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgbackups.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgclusters.yaml b/config/crd/patches/versionlabel_in_perconapgclusters.yaml index 2779a808a2..8a4bf1231a 100644 --- a/config/crd/patches/versionlabel_in_perconapgclusters.yaml +++ b/config/crd/patches/versionlabel_in_perconapgclusters.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgclusters.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgrestores.yaml b/config/crd/patches/versionlabel_in_perconapgrestores.yaml index 29161c8d9c..b9c11c6953 100644 --- a/config/crd/patches/versionlabel_in_perconapgrestores.yaml +++ b/config/crd/patches/versionlabel_in_perconapgrestores.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgrestores.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml index 17b3ed4c15..0becb36acf 100644 --- a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml +++ b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgupgrades.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 50d3be43b0..6305e11052 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -8,4 +8,4 @@ resources: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: main diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index da7695bf97..4936ba9299 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -9,4 +9,4 @@ patchesStrategicMerge: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: main diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 5e3b2e7dab..23697bfaf9 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -10,4 +10,4 @@ patchesStrategicMerge: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: main diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 4bfabc4df2..16d36f51b9 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53964,7 +53964,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index ab2e5baf80..bdd17d33fb 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,9 +9,9 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: 2.8.1 + crVersion: 2.9.0 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: docker.io/percona/percona-distribution-postgresql:17.7-1 + image: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -188,7 +188,7 @@ spec: # - secretRef: # name: instance-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -312,7 +312,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: docker.io/percona/percona-pgbouncer:1.25.0-1 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 # env: # - name: MY_ENV # value: "1000" @@ -409,7 +409,7 @@ spec: pgbackrest: # metadata: # labels: - image: docker.io/percona/percona-pgbackrest:2.57.0-1 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 # env: # - name: MY_ENV # value: "1000" @@ -417,7 +417,7 @@ spec: # - secretRef: # name: repo-host-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -613,7 +613,7 @@ spec: pmm: enabled: false - image: docker.io/percona/pmm-client:3.5.0 + image: docker.io/perconalab/pmm-client:dev-latest # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -647,7 +647,7 @@ spec: # - basebackup # extensions: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/perconalab/percona-postgresql-operator:main # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 3c278b8a58..f6f316458f 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 66dfcf83b3..2f66ce2184 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53962,7 +53962,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index d9869a9849..7861413845 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index e00b14a588..c6c492333b 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index b685fc5f2f..59ddf91d3b 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: docker.io/percona/percona-postgresql-operator:2.8.1-upgrade + image: docker.io/perconalab/percona-postgresql-operator:main-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.7-1 - toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.25.0-1 - toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.57.0-1 + toPostgresImage: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres + toPgBouncerImage: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 + toPgBackRestImage: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 diff --git a/e2e-tests/tests/init-deploy/05-assert.yaml b/e2e-tests/tests/init-deploy/05-assert.yaml index 751bfddb26..86b1aa02c3 100644 --- a/e2e-tests/tests/init-deploy/05-assert.yaml +++ b/e2e-tests/tests/init-deploy/05-assert.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -81,7 +81,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -144,7 +144,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -168,7 +168,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -191,7 +191,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" @@ -214,7 +214,7 @@ spec: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" diff --git a/e2e-tests/tests/upgrade-consistency/01-assert.yaml b/e2e-tests/tests/upgrade-consistency/01-assert.yaml index 60b019bcef..f50e94bdae 100644 --- a/e2e-tests/tests/upgrade-consistency/01-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-assert.yaml @@ -122,7 +122,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.6.0 + crVersion: 2.7.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml index 53c32fbcbe..4cde0661b8 100644 --- a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.6.0" + cr_version="2.7.0" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ diff --git a/e2e-tests/tests/upgrade-consistency/02-assert.yaml b/e2e-tests/tests/upgrade-consistency/02-assert.yaml index 4bce8de813..5b4bf418b8 100644 --- a/e2e-tests/tests/upgrade-consistency/02-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.7.0 + crVersion: 2.8.1 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index f35c4dd88d..6a234c9829 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.7.0" + cr_version="2.8.1" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ - \ | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ diff --git a/e2e-tests/tests/upgrade-consistency/03-assert.yaml b/e2e-tests/tests/upgrade-consistency/03-assert.yaml index 4a92c0a70a..1382b3ea26 100644 --- a/e2e-tests/tests/upgrade-consistency/03-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.8.1 + crVersion: 2.9.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 6b1149993c..39867d5f74 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.8.1" + cr_version="2.9.0" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ diff --git a/percona/controller/testdata/sidecar-resources-cr.yaml b/percona/controller/testdata/sidecar-resources-cr.yaml index 1c137a6ead..aa347ddfd9 100644 --- a/percona/controller/testdata/sidecar-resources-cr.yaml +++ b/percona/controller/testdata/sidecar-resources-cr.yaml @@ -4,7 +4,7 @@ kind: PerconaPGCluster metadata: name: cluster1 spec: - crVersion: 2.8.0 + crVersion: 2.9.0 image: perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always diff --git a/percona/version/version.txt b/percona/version/version.txt index dbe5900654..c8e38b6140 100644 --- a/percona/version/version.txt +++ b/percona/version/version.txt @@ -1 +1 @@ -2.8.1 +2.9.0 From 23ea0d5c19494ab7aa07b25e4d3876dfef89acd9 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Wed, 17 Dec 2025 00:30:06 +0200 Subject: [PATCH 233/300] Fix upgrade consistency and add major PG18 --- .../major-upgrade/01-create-cluster.yaml | 2 +- .../tests/major-upgrade/20-17-to-18.yaml | 24 +++++++++++ e2e-tests/tests/major-upgrade/20-assert.yaml | 42 +++++++++++++++++++ e2e-tests/tests/major-upgrade/21-assert.yaml | 21 ++++++++++ e2e-tests/tests/major-upgrade/22-assert.yaml | 31 ++++++++++++++ .../tests/major-upgrade/22-run-backup.yaml | 9 ++++ e2e-tests/tests/major-upgrade/23-assert.yaml | 10 +++++ .../major-upgrade/23-read-from-primary.yaml | 12 ++++++ .../01-create-cluster.yaml | 14 ++----- .../upgrade-consistency/02-patch-cluster.yaml | 12 +----- .../upgrade-consistency/03-patch-cluster.yaml | 7 +--- 11 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 e2e-tests/tests/major-upgrade/20-17-to-18.yaml create mode 100644 e2e-tests/tests/major-upgrade/20-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade/21-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade/22-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade/22-run-backup.yaml create mode 100644 e2e-tests/tests/major-upgrade/23-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade/23-read-from-primary.yaml diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml index ad23c41e3d..adb3d39877 100644 --- a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml +++ b/e2e-tests/tests/major-upgrade/01-create-cluster.yaml @@ -16,5 +16,5 @@ commands: .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-pgbouncer13" | .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-pgbackrest13" | .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | - .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.1"}]' \ + .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.6"}]' \ | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade/20-17-to-18.yaml b/e2e-tests/tests/major-upgrade/20-17-to-18.yaml new file mode 100644 index 0000000000..7c60208223 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/20-17-to-18.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + kubectl apply -n ${NAMESPACE} -f - <<-EOF + apiVersion: pgv2.percona.com/v2 + kind: PerconaPGUpgrade + metadata: + name: 17-to-18 + spec: + postgresClusterName: major-upgrade + image: ${IMAGE_UPGRADE} + fromPostgresVersion: 17 + toPostgresVersion: 18 + toPostgresImage: $(get_container_image "postgres" 18) + toPgBouncerImage: $(get_container_image "pgbouncer" 18) + toPgBackRestImage: $(get_container_image "pgbackrest" 18) + EOF + diff --git a/e2e-tests/tests/major-upgrade/20-assert.yaml b/e2e-tests/tests/major-upgrade/20-assert.yaml new file mode 100644 index 0000000000..ed27544cb4 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/20-assert.yaml @@ -0,0 +1,42 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 360 +commands: +- script: |- + kubectl -n ${NAMESPACE} get pg,pod,job + sleep 5 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: major-upgrade +spec: + postgresVersion: 18 +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 diff --git a/e2e-tests/tests/major-upgrade/21-assert.yaml b/e2e-tests/tests/major-upgrade/21-assert.yaml new file mode 100644 index 0000000000..6af985e4b7 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/21-assert.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 660 +commands: +- script: |- + kubectl get postgrescluster major-upgrade \ + -n ${NAMESPACE} \ + -o yaml \ + | yq eval '.status.pgbackrest.repos' - +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: major-upgrade +status: + pgbackrest: + repos: + - bound: true + name: repo4 + replicaCreateBackupComplete: true + stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/22-assert.yaml b/e2e-tests/tests/major-upgrade/22-assert.yaml new file mode 100644 index 0000000000..38642a86fb --- /dev/null +++ b/e2e-tests/tests/major-upgrade/22-assert.yaml @@ -0,0 +1,31 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 660 +--- +kind: Job +apiVersion: batch/v1 +metadata: + annotations: + postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-17-to-18 + labels: + postgres-operator.crunchydata.com/pgbackrest-backup: manual + postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGBackup +metadata: + name: backup-after-17-to-18 +spec: + pgCluster: major-upgrade + repoName: repo4 + options: + - --type=full +status: + state: Succeeded diff --git a/e2e-tests/tests/major-upgrade/22-run-backup.yaml b/e2e-tests/tests/major-upgrade/22-run-backup.yaml new file mode 100644 index 0000000000..105493b19c --- /dev/null +++ b/e2e-tests/tests/major-upgrade/22-run-backup.yaml @@ -0,0 +1,9 @@ +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGBackup +metadata: + name: backup-after-17-to-18 +spec: + pgCluster: major-upgrade + repoName: repo4 + options: + - --type=full diff --git a/e2e-tests/tests/major-upgrade/23-assert.yaml b/e2e-tests/tests/major-upgrade/23-assert.yaml new file mode 100644 index 0000000000..15c83197aa --- /dev/null +++ b/e2e-tests/tests/major-upgrade/23-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 23-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/23-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/23-read-from-primary.yaml new file mode 100644 index 0000000000..48798197b8 --- /dev/null +++ b/e2e-tests/tests/major-upgrade/23-read-from-primary.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 23-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml index e0c05f018f..68577d8b6d 100644 --- a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml @@ -8,15 +8,7 @@ commands: source ../../functions - cr_version="2.7.0" - - backrest_image=$(get_version_images $cr_version BACKREST${PG_VER}) - pgbouncer_image=$(get_version_images $cr_version PGBOUNCER${PG_VER}) - postgres_image=$(get_version_images $cr_version POSTGRESQL${PG_VER}) - get_cr \ - | yq eval ".spec.crVersion=\"$cr_version\"" - \ - | yq eval ".spec.image=\"${REGISTRY_NAME_FULL}${postgres_image}\"" - \ - | yq eval ".spec.backups.pgbackrest.image=\"${REGISTRY_NAME_FULL}${backrest_image}\"" - \ - | yq eval ".spec.proxy.pgBouncer.image=\"${REGISTRY_NAME_FULL}${pgbouncer_image}\"" - \ - | kubectl -n "${NAMESPACE}" apply -f - \ No newline at end of file + | yq eval ' + .spec.crVersion="2.7.0"' - \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index be63327426..d26938bd37 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -8,17 +8,9 @@ commands: source ../../functions - cr_version="2.8.1" - - backrest_image=$(get_version_images $cr_version BACKREST${PG_VER} ) - pgbouncer_image=$(get_version_images $cr_version PGBOUNCER${PG_VER}) - postgres_image=$(get_version_images $cr_version POSTGRESQL${PG_VER}) - get_cr \ - | yq eval ".spec.crVersion=\"$cr_version\"" - \ - | yq eval ".spec.image=\"${REGISTRY_NAME_FULL}${postgres_image}\"" - \ - | yq eval ".spec.backups.pgbackrest.image=\"${REGISTRY_NAME_FULL}${backrest_image}\"" - \ - | yq eval ".spec.proxy.pgBouncer.image=\"${REGISTRY_NAME_FULL}${pgbouncer_image}\"" - \ + | yq eval ' + .spec.crVersion="2.8.1"' - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 39867d5f74..0c71840cba 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -8,12 +8,9 @@ commands: source ../../functions - cr_version="2.9.0" get_cr \ - | yq eval ".spec.crVersion=\"$cr_version\"" - \ - | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ - | yq eval ".spec.backups.pgbackrest.image=\"${IMAGE_BASE}:main-pgbackrest$PG_VER\"" - \ - | yq eval ".spec.proxy.pgBouncer.image=\"${IMAGE_BASE}:main-pgbouncer$PG_VER\"" - \ + | yq eval ' + .spec.crVersion="2.9.0"' - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 From 41a695ae2813345fa49a753d266b41ece763a3bb Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Mon, 22 Dec 2025 17:35:04 +0200 Subject: [PATCH 234/300] K8SPG-919 Update versions for 2.8.2 release (#1386) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * K8SPG-919 Update versions for 2.8.2 release * fix envtest --------- Co-authored-by: Ege Güneş --- Makefile | 6 +++- .../pgv2.percona.com_perconapgupgrades.yaml | 2 +- config/bundle/kustomization.yaml | 2 +- .../pgv2.percona.com_perconapgclusters.yaml | 2 +- .../versionlabel_in_perconapgbackups.yaml | 2 +- .../versionlabel_in_perconapgclusters.yaml | 2 +- .../versionlabel_in_perconapgrestores.yaml | 2 +- .../versionlabel_in_perconapgupgrade.yaml | 2 +- config/cw-bundle/kustomization.yaml | 2 +- config/manager/cluster/kustomization.yaml | 2 +- config/manager/namespace/kustomization.yaml | 2 +- deploy/bundle.yaml | 12 ++++---- deploy/cr.yaml | 12 ++++---- deploy/crd.yaml | 8 +++--- deploy/cw-bundle.yaml | 12 ++++---- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 4 +-- e2e-tests/release_versions | 28 +++++++++---------- e2e-tests/tests/init-deploy/05-assert.yaml | 12 ++++---- .../tests/upgrade-consistency/03-assert.yaml | 2 +- .../upgrade-consistency/03-patch-cluster.yaml | 2 +- .../postgrescluster/controller_test.go | 8 +++--- percona/version/version.txt | 2 +- .../v2/perconapgupgrade_types.go | 2 +- 25 files changed, 69 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index 528b983dbb..c8da28b3eb 100644 --- a/Makefile +++ b/Makefile @@ -443,6 +443,9 @@ rm -rf $$TMP_DIR ;\ } endef +update-version: + echo $(NEXT_VER) > percona/version/version.txt + # Prepare release PG_VER ?= $(shell grep -o "postgresVersion: .*" deploy/cr.yaml|grep -oE "[0-9]+") include e2e-tests/release_versions @@ -469,11 +472,12 @@ MINOR_VER := $(word 2,$(subst ., ,$(CURRENT_VERSION))) NEXT_VER := $(MAJOR_VER).$(shell expr $(MINOR_VER) + 1).0 PREV1_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 1).0 PREV2_VERSION := $(MAJOR_VER).$(shell expr $(MINOR_VER) - 2).0 -after-release: generate +after-release: update-version generate echo $(NEXT_VER) > percona/version/version.txt $(SED) -i \ -e "/^spec:/,/^ crVersion:/{s/crVersion: .*/crVersion: $(NEXT_VER)/}" \ -e "/^spec:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-ppg$(PG_VER)-postgres#}" \ + -e "/initContainer:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ -e "/^ pgBouncer:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbouncer$(PG_VER)#}" \ -e "/^ pgbackrest:/,/^ image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main-pgbackrest$(PG_VER)#}" \ -e "/extensions:/,/image:/{s#image: .*#image: $(REGISTRY_NAME_FULL)perconalab/percona-postgresql-operator:main#}" \ diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml index 8418316924..b065955532 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml @@ -954,7 +954,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 16 + maximum: 17 minimum: 12 type: integer image: diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index 351b02520f..7649b09c76 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -7,4 +7,4 @@ resources: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: 2.8.2 diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index f807fa7e13..63f540edd2 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -22859,7 +22859,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 16 + maximum: 17 minimum: 12 type: integer image: diff --git a/config/crd/patches/versionlabel_in_perconapgbackups.yaml b/config/crd/patches/versionlabel_in_perconapgbackups.yaml index 771acd9abe..445f49b70a 100644 --- a/config/crd/patches/versionlabel_in_perconapgbackups.yaml +++ b/config/crd/patches/versionlabel_in_perconapgbackups.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgbackups.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 diff --git a/config/crd/patches/versionlabel_in_perconapgclusters.yaml b/config/crd/patches/versionlabel_in_perconapgclusters.yaml index 2779a808a2..efb69476af 100644 --- a/config/crd/patches/versionlabel_in_perconapgclusters.yaml +++ b/config/crd/patches/versionlabel_in_perconapgclusters.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgclusters.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 diff --git a/config/crd/patches/versionlabel_in_perconapgrestores.yaml b/config/crd/patches/versionlabel_in_perconapgrestores.yaml index 29161c8d9c..5b2977ddcc 100644 --- a/config/crd/patches/versionlabel_in_perconapgrestores.yaml +++ b/config/crd/patches/versionlabel_in_perconapgrestores.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgrestores.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 diff --git a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml index 17b3ed4c15..1a5ea0fe62 100644 --- a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml +++ b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgupgrades.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 50d3be43b0..29d3a6e4a2 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -8,4 +8,4 @@ resources: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: 2.8.2 diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index da7695bf97..da55ec7165 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -9,4 +9,4 @@ patchesStrategicMerge: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: 2.8.2 diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 5e3b2e7dab..01d84e6b27 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -10,4 +10,4 @@ patchesStrategicMerge: images: - name: postgres-operator newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.1 + newTag: 2.8.2 diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 4bfabc4df2..c5477d2775 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -23160,7 +23160,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 16 + maximum: 17 minimum: 12 type: integer image: @@ -53964,7 +53964,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/percona/percona-postgresql-operator:2.8.2 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index ab2e5baf80..b55deefcc0 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,9 +9,9 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: 2.8.1 + crVersion: 2.8.2 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/percona/percona-postgresql-operator:2.8.2 # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: docker.io/percona/percona-distribution-postgresql:17.7-1 + image: docker.io/percona/percona-distribution-postgresql:17.7-2 imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -188,7 +188,7 @@ spec: # - secretRef: # name: instance-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/percona/percona-postgresql-operator:2.8.2 # resources: # limits: # cpu: 2.0 @@ -417,7 +417,7 @@ spec: # - secretRef: # name: repo-host-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/percona/percona-postgresql-operator:2.8.2 # resources: # limits: # cpu: 2.0 @@ -647,7 +647,7 @@ spec: # - basebackup # extensions: -# image: docker.io/percona/percona-postgresql-operator:2.8.1 +# image: docker.io/percona/percona-postgresql-operator:2.8.2 # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 3c278b8a58..a63bbfa30b 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 66dfcf83b3..6b00545443 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.1 + pgv2.percona.com/version: v2.8.2 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -23160,7 +23160,7 @@ spec: type: object fromPostgresVersion: description: The major version of PostgreSQL before the upgrade. - maximum: 16 + maximum: 17 minimum: 12 type: integer image: @@ -53962,7 +53962,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/percona/percona-postgresql-operator:2.8.2 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index d9869a9849..73b3029fe2 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/percona/percona-postgresql-operator:2.8.2 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index e00b14a588..cc18851e77 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.1 + image: docker.io/percona/percona-postgresql-operator:2.8.2 imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index b685fc5f2f..86264fbc9c 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: docker.io/percona/percona-postgresql-operator:2.8.1-upgrade + image: docker.io/percona/percona-postgresql-operator:2.8.2-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.7-1 + toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.7-2 toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.25.0-1 toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.57.0-1 diff --git a/e2e-tests/release_versions b/e2e-tests/release_versions index 5b0bc10bc7..a2e8c4900e 100644 --- a/e2e-tests/release_versions +++ b/e2e-tests/release_versions @@ -1,37 +1,37 @@ # Images versions -IMAGE_OPERATOR=percona/percona-postgresql-operator:2.8.1 +IMAGE_OPERATOR=percona/percona-postgresql-operator:2.8.2 -IMAGE_POSTGRESQL18=percona/percona-distribution-postgresql:18.1-1 +IMAGE_POSTGRESQL18=percona/percona-distribution-postgresql:18.1-3 IMAGE_PGBOUNCER18=percona/percona-pgbouncer:1.25.0-1 -IMAGE_POSTGIS18=percona/percona-postgresql-operator:2.8.1-ppg18.1-postgres-gis3.5.4 +IMAGE_POSTGIS18=percona/percona-postgresql-operator:2.8.2-ppg18.1-postgres-gis3.5.4 IMAGE_BACKREST18=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL17=percona/percona-distribution-postgresql:17.7-1 +IMAGE_POSTGRESQL17=percona/percona-distribution-postgresql:17.7-2 IMAGE_PGBOUNCER17=percona/percona-pgbouncer:1.25.0-1 -IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.8.1-ppg17.7-postgres-gis3.3.8 +IMAGE_POSTGIS17=percona/percona-postgresql-operator:2.8.2-ppg17.7-postgres-gis3.3.8 IMAGE_BACKREST17=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL16=percona/percona-distribution-postgresql:16.11-1 +IMAGE_POSTGRESQL16=percona/percona-distribution-postgresql:16.11-2 IMAGE_PGBOUNCER16=percona/percona-pgbouncer:1.25.0-1 -IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.8.1-ppg16.11-postgres-gis3.3.8 +IMAGE_POSTGIS16=percona/percona-postgresql-operator:2.8.2-ppg16.11-postgres-gis3.3.8 IMAGE_BACKREST16=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL15=percona/percona-distribution-postgresql:15.15-1 +IMAGE_POSTGRESQL15=percona/percona-distribution-postgresql:15.15-2 IMAGE_PGBOUNCER15=percona/percona-pgbouncer:1.25.0-1 -IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.8.1-ppg15.15-postgres-gis3.3.8 +IMAGE_POSTGIS15=percona/percona-postgresql-operator:2.8.2-ppg15.15-postgres-gis3.3.8 IMAGE_BACKREST15=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL14=percona/percona-distribution-postgresql:14.20-1 +IMAGE_POSTGRESQL14=percona/percona-distribution-postgresql:14.20-2 IMAGE_PGBOUNCER14=percona/percona-pgbouncer:1.25.0-1 -IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.8.1-ppg14.20-postgres-gis3.3.8 +IMAGE_POSTGIS14=percona/percona-postgresql-operator:2.8.2-ppg14.20-postgres-gis3.3.8 IMAGE_BACKREST14=percona/percona-pgbackrest:2.57.0-1 -IMAGE_POSTGRESQL13=percona/percona-distribution-postgresql:13.23-1 +IMAGE_POSTGRESQL13=percona/percona-distribution-postgresql:13.23-2 IMAGE_PGBOUNCER13=percona/percona-pgbouncer:1.25.0-1 -IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.8.1-ppg13.23-postgres-gis3.3.8 +IMAGE_POSTGIS13=percona/percona-postgresql-operator:2.8.2-ppg13.23-postgres-gis3.3.8 IMAGE_BACKREST13=percona/percona-pgbackrest:2.57.0-1 -IMAGE_UPGRADE=percona/percona-postgresql-operator:2.8.1-upgrade +IMAGE_UPGRADE=percona/percona-postgresql-operator:2.8.2-upgrade IMAGE_PMM_CLIENT=percona/pmm-client:2.44.1-1 IMAGE_PMM_SERVER=percona/pmm-server:2.44.1 diff --git a/e2e-tests/tests/init-deploy/05-assert.yaml b/e2e-tests/tests/init-deploy/05-assert.yaml index 751bfddb26..e6c85c5e8b 100644 --- a/e2e-tests/tests/init-deploy/05-assert.yaml +++ b/e2e-tests/tests/init-deploy/05-assert.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.8.2 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -81,7 +81,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.8.2 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -144,7 +144,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.8.2 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -168,7 +168,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.8.2 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -191,7 +191,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.8.2 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" @@ -214,7 +214,7 @@ spec: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.1 + pgv2.percona.com/version: 2.8.2 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" diff --git a/e2e-tests/tests/upgrade-consistency/03-assert.yaml b/e2e-tests/tests/upgrade-consistency/03-assert.yaml index 4a92c0a70a..40ae702403 100644 --- a/e2e-tests/tests/upgrade-consistency/03-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.8.1 + crVersion: 2.8.2 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 6b1149993c..316502decc 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.8.1" + cr_version="2.8.2" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ diff --git a/internal/controller/postgrescluster/controller_test.go b/internal/controller/postgrescluster/controller_test.go index 73723d63d0..d47630900b 100644 --- a/internal/controller/postgrescluster/controller_test.go +++ b/internal/controller/postgrescluster/controller_test.go @@ -93,7 +93,7 @@ var olmClusterYAML = ` metadata: name: olm spec: - postgresVersion: 13 + postgresVersion: 17 image: postgres instances: - name: register-now @@ -231,7 +231,7 @@ var _ = Describe("PostgresCluster Reconciler", func() { metadata: name: carlos spec: - postgresVersion: 13 + postgresVersion: 17 image: postgres instances: - name: samba @@ -438,7 +438,7 @@ spec: metadata: name: carlos spec: - postgresVersion: 13 + postgresVersion: 17 image: postgres instances: - name: samba @@ -660,7 +660,7 @@ spec: metadata: name: test-cluster spec: - postgresVersion: 13 + postgresVersion: 17 image: postgres instances: - name: instance1 diff --git a/percona/version/version.txt b/percona/version/version.txt index dbe5900654..1817afea41 100644 --- a/percona/version/version.txt +++ b/percona/version/version.txt @@ -1 +1 @@ -2.8.1 +2.8.2 diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go index 5b5797627e..e8dbce4a92 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgupgrade_types.go @@ -59,7 +59,7 @@ type PerconaPGUpgradeSpec struct { // The major version of PostgreSQL before the upgrade. // +kubebuilder:validation:Required // +kubebuilder:validation:Minimum=12 - // +kubebuilder:validation:Maximum=16 + // +kubebuilder:validation:Maximum=17 FromPostgresVersion int `json:"fromPostgresVersion"` // The major version of PostgreSQL to be upgraded to. From 2da488093c5cdcb8676a04ee0561887102f45ece Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 01:01:29 +0000 Subject: [PATCH 235/300] CLOUD-727: Bump github.com/go-openapi/swag from 0.25.3 to 0.25.4 Bumps [github.com/go-openapi/swag](https://github.com/go-openapi/swag) from 0.25.3 to 0.25.4. - [Commits](https://github.com/go-openapi/swag/compare/v0.25.3...v0.25.4) --- updated-dependencies: - dependency-name: github.com/go-openapi/swag dependency-version: 0.25.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 24 ++++++++++++------------ go.sum | 52 ++++++++++++++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index c7736b5db3..cd2501d7e3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/go-openapi/errors v0.22.4 github.com/go-openapi/runtime v0.29.2 github.com/go-openapi/strfmt v0.25.0 - github.com/go-openapi/swag v0.25.3 + github.com/go-openapi/swag v0.25.4 github.com/go-openapi/validate v0.25.1 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 @@ -46,17 +46,17 @@ require ( github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/go-openapi/swag/cmdutils v0.25.3 // indirect - github.com/go-openapi/swag/conv v0.25.3 // indirect - github.com/go-openapi/swag/fileutils v0.25.3 // indirect - github.com/go-openapi/swag/jsonname v0.25.3 // indirect - github.com/go-openapi/swag/jsonutils v0.25.3 // indirect - github.com/go-openapi/swag/loading v0.25.3 // indirect - github.com/go-openapi/swag/mangling v0.25.3 // indirect - github.com/go-openapi/swag/netutils v0.25.3 // indirect - github.com/go-openapi/swag/stringutils v0.25.3 // indirect - github.com/go-openapi/swag/typeutils v0.25.3 // indirect - github.com/go-openapi/swag/yamlutils v0.25.3 // indirect + github.com/go-openapi/swag/cmdutils v0.25.4 // indirect + github.com/go-openapi/swag/conv v0.25.4 // indirect + github.com/go-openapi/swag/fileutils v0.25.4 // indirect + github.com/go-openapi/swag/jsonname v0.25.4 // indirect + github.com/go-openapi/swag/jsonutils v0.25.4 // indirect + github.com/go-openapi/swag/loading v0.25.4 // indirect + github.com/go-openapi/swag/mangling v0.25.4 // indirect + github.com/go-openapi/swag/netutils v0.25.4 // indirect + github.com/go-openapi/swag/stringutils v0.25.4 // indirect + github.com/go-openapi/swag/typeutils v0.25.4 // indirect + github.com/go-openapi/swag/yamlutils v0.25.4 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/btree v1.1.3 // indirect diff --git a/go.sum b/go.sum index 38001875e1..8fac9cc207 100644 --- a/go.sum +++ b/go.sum @@ -63,32 +63,32 @@ github.com/go-openapi/spec v0.22.1 h1:beZMa5AVQzRspNjvhe5aG1/XyBSMeX1eEOs7dMoXh/ github.com/go-openapi/spec v0.22.1/go.mod h1:c7aeIQT175dVowfp7FeCvXXnjN/MrpaONStibD2WtDA= github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ= github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8= -github.com/go-openapi/swag v0.25.3 h1:FAa5wJXyDtI7yUztKDfZxDrSx+8WTg31MfCQ9s3PV+s= -github.com/go-openapi/swag v0.25.3/go.mod h1:tX9vI8Mj8Ny+uCEk39I1QADvIPI7lkndX4qCsEqhkS8= -github.com/go-openapi/swag/cmdutils v0.25.3 h1:EIwGxN143JCThNHnqfqs85R8lJcJG06qjJRZp3VvjLI= -github.com/go-openapi/swag/cmdutils v0.25.3/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= -github.com/go-openapi/swag/conv v0.25.3 h1:PcB18wwfba7MN5BVlBIV+VxvUUeC2kEuCEyJ2/t2X7E= -github.com/go-openapi/swag/conv v0.25.3/go.mod h1:n4Ibfwhn8NJnPXNRhBO5Cqb9ez7alBR40JS4rbASUPU= -github.com/go-openapi/swag/fileutils v0.25.3 h1:P52Uhd7GShkeU/a1cBOuqIcHMHBrA54Z2t5fLlE85SQ= -github.com/go-openapi/swag/fileutils v0.25.3/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= -github.com/go-openapi/swag/jsonname v0.25.3 h1:U20VKDS74HiPaLV7UZkztpyVOw3JNVsit+w+gTXRj0A= -github.com/go-openapi/swag/jsonname v0.25.3/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= -github.com/go-openapi/swag/jsonutils v0.25.3 h1:kV7wer79KXUM4Ea4tBdAVTU842Rg6tWstX3QbM4fGdw= -github.com/go-openapi/swag/jsonutils v0.25.3/go.mod h1:ILcKqe4HC1VEZmJx51cVuZQ6MF8QvdfXsQfiaCs0z9o= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3 h1:/i3E9hBujtXfHy91rjtwJ7Fgv5TuDHgnSrYjhFxwxOw= -github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3/go.mod h1:8kYfCR2rHyOj25HVvxL5Nm8wkfzggddgjZm6RgjT8Ao= -github.com/go-openapi/swag/loading v0.25.3 h1:Nn65Zlzf4854MY6Ft0JdNrtnHh2bdcS/tXckpSnOb2Y= -github.com/go-openapi/swag/loading v0.25.3/go.mod h1:xajJ5P4Ang+cwM5gKFrHBgkEDWfLcsAKepIuzTmOb/c= -github.com/go-openapi/swag/mangling v0.25.3 h1:rGIrEzXaYWuUW1MkFmG3pcH+EIA0/CoUkQnIyB6TUyo= -github.com/go-openapi/swag/mangling v0.25.3/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= -github.com/go-openapi/swag/netutils v0.25.3 h1:XWXHZfL/65ABiv8rvGp9dtE0C6QHTYkCrNV77jTl358= -github.com/go-openapi/swag/netutils v0.25.3/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= -github.com/go-openapi/swag/stringutils v0.25.3 h1:nAmWq1fUTWl/XiaEPwALjp/8BPZJun70iDHRNq/sH6w= -github.com/go-openapi/swag/stringutils v0.25.3/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= -github.com/go-openapi/swag/typeutils v0.25.3 h1:2w4mEEo7DQt3V4veWMZw0yTPQibiL3ri2fdDV4t2TQc= -github.com/go-openapi/swag/typeutils v0.25.3/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= -github.com/go-openapi/swag/yamlutils v0.25.3 h1:LKTJjCn/W1ZfMec0XDL4Vxh8kyAnv1orH5F2OREDUrg= -github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao= +github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU= +github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ= +github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4= +github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0= +github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4= +github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU= +github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y= +github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk= +github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= +github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= +github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA= +github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM= +github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s= +github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE= +github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48= +github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg= +github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0= +github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg= +github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8= +github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0= +github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw= +github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE= +github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw= +github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc= github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4= github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg= github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls= From 626658ebcbdfab55e5934f8a50491eb177a41a3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 01:01:31 +0000 Subject: [PATCH 236/300] CLOUD-727: Bump github.com/hashicorp/go-version from 1.7.0 to 1.8.0 Bumps [github.com/hashicorp/go-version](https://github.com/hashicorp/go-version) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/hashicorp/go-version/releases) - [Changelog](https://github.com/hashicorp/go-version/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/go-version/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/go-version dependency-version: 1.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c7736b5db3..7541a5913a 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/go-openapi/validate v0.25.1 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 - github.com/hashicorp/go-version v1.7.0 + github.com/hashicorp/go-version v1.8.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 github.com/onsi/ginkgo/v2 v2.27.2 github.com/onsi/gomega v1.38.2 diff --git a/go.sum b/go.sum index 38001875e1..3e57b17ece 100644 --- a/go.sum +++ b/go.sum @@ -128,8 +128,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4z github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= From 180c3ed3a492ffe58e1178077777aba0e8b7f1d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 01:01:33 +0000 Subject: [PATCH 237/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace Bumps [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) from 1.38.0 to 1.39.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.38.0...v1.39.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace dependency-version: 1.39.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 12 ++++++------ go.sum | 28 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index c7736b5db3..3722e71cb2 100644 --- a/go.mod +++ b/go.mod @@ -22,12 +22,12 @@ require ( github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.33.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 - go.opentelemetry.io/otel v1.38.0 + go.opentelemetry.io/otel v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 - go.opentelemetry.io/otel/sdk v1.38.0 - go.opentelemetry.io/otel/trace v1.38.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 + go.opentelemetry.io/otel/sdk v1.39.0 + go.opentelemetry.io/otel/trace v1.39.0 go.uber.org/zap v1.27.1 golang.org/x/crypto v0.45.0 google.golang.org/grpc v1.77.0 @@ -119,13 +119,13 @@ require ( go.mongodb.org/mongo-driver v1.17.6 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect - go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect go.opentelemetry.io/proto/otlp v1.7.1 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.32.0 // indirect golang.org/x/sync v0.18.0 // indirect - golang.org/x/sys v0.38.0 // indirect + golang.org/x/sys v0.39.0 // indirect golang.org/x/term v0.37.0 // indirect golang.org/x/text v0.31.0 // indirect golang.org/x/time v0.9.0 // indirect diff --git a/go.sum b/go.sum index 38001875e1..8d82e4349e 100644 --- a/go.sum +++ b/go.sum @@ -257,22 +257,22 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= -go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= -go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE= -go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= -go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= -go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= -go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= -go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= -go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= -go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= -go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 h1:8UPA4IbVZxpsD76ihGOQiFml99GPAEZLohDXvqHdi6U= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0/go.mod h1:MZ1T/+51uIVKlRzGw1Fo46KEWThjlCBZKl2LzY5nv4g= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -320,8 +320,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= From 40bd1ea89fe858e2f15d736ada142289c527110f Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Mon, 5 Jan 2026 16:47:05 +0200 Subject: [PATCH 238/300] Revert images back to main after 2.8.2 release (#1387) --- config/bundle/kustomization.yaml | 4 ++-- .../versionlabel_in_perconapgbackups.yaml | 2 +- .../versionlabel_in_perconapgclusters.yaml | 2 +- .../versionlabel_in_perconapgrestores.yaml | 2 +- .../versionlabel_in_perconapgupgrade.yaml | 2 +- config/cw-bundle/kustomization.yaml | 4 ++-- config/manager/cluster/kustomization.yaml | 4 ++-- config/manager/namespace/kustomization.yaml | 4 ++-- deploy/bundle.yaml | 10 +++++----- deploy/cr.yaml | 18 +++++++++--------- deploy/crd.yaml | 8 ++++---- deploy/cw-bundle.yaml | 10 +++++----- deploy/cw-operator.yaml | 2 +- deploy/operator.yaml | 2 +- deploy/upgrade.yaml | 8 ++++---- e2e-tests/tests/init-deploy/05-assert.yaml | 12 ++++++------ .../tests/upgrade-consistency/01-assert.yaml | 2 +- .../upgrade-consistency/01-create-cluster.yaml | 2 +- .../tests/upgrade-consistency/02-assert.yaml | 2 +- .../upgrade-consistency/02-patch-cluster.yaml | 2 +- .../tests/upgrade-consistency/03-assert.yaml | 2 +- .../upgrade-consistency/03-patch-cluster.yaml | 2 +- .../testdata/sidecar-resources-cr.yaml | 2 +- percona/version/version.txt | 2 +- 24 files changed, 55 insertions(+), 55 deletions(-) diff --git a/config/bundle/kustomization.yaml b/config/bundle/kustomization.yaml index 7649b09c76..90cf89956e 100644 --- a/config/bundle/kustomization.yaml +++ b/config/bundle/kustomization.yaml @@ -6,5 +6,5 @@ resources: - ../manager/namespace images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.2 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/crd/patches/versionlabel_in_perconapgbackups.yaml b/config/crd/patches/versionlabel_in_perconapgbackups.yaml index 445f49b70a..3c32866138 100644 --- a/config/crd/patches/versionlabel_in_perconapgbackups.yaml +++ b/config/crd/patches/versionlabel_in_perconapgbackups.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgbackups.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgclusters.yaml b/config/crd/patches/versionlabel_in_perconapgclusters.yaml index efb69476af..8a4bf1231a 100644 --- a/config/crd/patches/versionlabel_in_perconapgclusters.yaml +++ b/config/crd/patches/versionlabel_in_perconapgclusters.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgclusters.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgrestores.yaml b/config/crd/patches/versionlabel_in_perconapgrestores.yaml index 5b2977ddcc..b9c11c6953 100644 --- a/config/crd/patches/versionlabel_in_perconapgrestores.yaml +++ b/config/crd/patches/versionlabel_in_perconapgrestores.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgrestores.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 diff --git a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml index 1a5ea0fe62..0becb36acf 100644 --- a/config/crd/patches/versionlabel_in_perconapgupgrade.yaml +++ b/config/crd/patches/versionlabel_in_perconapgupgrade.yaml @@ -3,4 +3,4 @@ kind: CustomResourceDefinition metadata: name: perconapgupgrades.pgv2.percona.com labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 diff --git a/config/cw-bundle/kustomization.yaml b/config/cw-bundle/kustomization.yaml index 29d3a6e4a2..440d098731 100644 --- a/config/cw-bundle/kustomization.yaml +++ b/config/cw-bundle/kustomization.yaml @@ -7,5 +7,5 @@ resources: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.2 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/manager/cluster/kustomization.yaml b/config/manager/cluster/kustomization.yaml index da55ec7165..6f8f4bf129 100644 --- a/config/manager/cluster/kustomization.yaml +++ b/config/manager/cluster/kustomization.yaml @@ -8,5 +8,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.2 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/config/manager/namespace/kustomization.yaml b/config/manager/namespace/kustomization.yaml index 01d84e6b27..a57ff786e0 100644 --- a/config/manager/namespace/kustomization.yaml +++ b/config/manager/namespace/kustomization.yaml @@ -9,5 +9,5 @@ patchesStrategicMerge: images: - name: postgres-operator - newName: docker.io/percona/percona-postgresql-operator - newTag: 2.8.2 + newName: docker.io/perconalab/percona-postgresql-operator + newTag: main diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index c5477d2775..1dda0baea3 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53964,7 +53964,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.2 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cr.yaml b/deploy/cr.yaml index b55deefcc0..bdd17d33fb 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -9,9 +9,9 @@ metadata: # - percona.com/delete-ssl # - percona.com/delete-backups spec: - crVersion: 2.8.2 + crVersion: 2.9.0 # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.2 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -154,7 +154,7 @@ spec: # test-label: value - image: docker.io/percona/percona-distribution-postgresql:17.7-2 + image: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always postgresVersion: 17 # port: 5432 @@ -188,7 +188,7 @@ spec: # - secretRef: # name: instance-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.2 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -312,7 +312,7 @@ spec: proxy: pgBouncer: replicas: 3 - image: docker.io/percona/percona-pgbouncer:1.25.0-1 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 # env: # - name: MY_ENV # value: "1000" @@ -409,7 +409,7 @@ spec: pgbackrest: # metadata: # labels: - image: docker.io/percona/percona-pgbackrest:2.57.0-1 + image: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 # env: # - name: MY_ENV # value: "1000" @@ -417,7 +417,7 @@ spec: # - secretRef: # name: repo-host-env-secret # initContainer: -# image: docker.io/percona/percona-postgresql-operator:2.8.2 +# image: docker.io/perconalab/percona-postgresql-operator:main # resources: # limits: # cpu: 2.0 @@ -613,7 +613,7 @@ spec: pmm: enabled: false - image: docker.io/percona/pmm-client:3.5.0 + image: docker.io/perconalab/pmm-client:dev-latest # imagePullPolicy: IfNotPresent secret: cluster1-pmm-secret serverHost: monitoring-service @@ -647,7 +647,7 @@ spec: # - basebackup # extensions: -# image: docker.io/percona/percona-postgresql-operator:2.8.2 +# image: docker.io/perconalab/percona-postgresql-operator:main # imagePullPolicy: Always # storage: # type: s3 diff --git a/deploy/crd.yaml b/deploy/crd.yaml index a63bbfa30b..f6f316458f 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 6b00545443..d339592195 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -297,7 +297,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -705,7 +705,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -22109,7 +22109,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -22209,7 +22209,7 @@ metadata: annotations: controller-gen.kubebuilder.io/version: v0.18.0 labels: - pgv2.percona.com/version: v2.8.2 + pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -53962,7 +53962,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.2 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 73b3029fe2..7861413845 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,7 +44,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.2 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/operator.yaml b/deploy/operator.yaml index cc18851e77..c6c492333b 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,7 +47,7 @@ spec: value: "false" - name: PGO_WORKERS value: "1" - image: docker.io/percona/percona-postgresql-operator:2.8.2 + image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: failureThreshold: 3 diff --git a/deploy/upgrade.yaml b/deploy/upgrade.yaml index 86264fbc9c..59ddf91d3b 100644 --- a/deploy/upgrade.yaml +++ b/deploy/upgrade.yaml @@ -4,9 +4,9 @@ metadata: name: cluster1-16-to-17 spec: postgresClusterName: cluster1 - image: docker.io/percona/percona-postgresql-operator:2.8.2-upgrade + image: docker.io/perconalab/percona-postgresql-operator:main-upgrade fromPostgresVersion: 16 toPostgresVersion: 17 - toPostgresImage: docker.io/percona/percona-distribution-postgresql:17.7-2 - toPgBouncerImage: docker.io/percona/percona-pgbouncer:1.25.0-1 - toPgBackRestImage: docker.io/percona/percona-pgbackrest:2.57.0-1 + toPostgresImage: docker.io/perconalab/percona-postgresql-operator:main-ppg17-postgres + toPgBouncerImage: docker.io/perconalab/percona-postgresql-operator:main-pgbouncer17 + toPgBackRestImage: docker.io/perconalab/percona-postgresql-operator:main-pgbackrest17 diff --git a/e2e-tests/tests/init-deploy/05-assert.yaml b/e2e-tests/tests/init-deploy/05-assert.yaml index e6c85c5e8b..86b1aa02c3 100644 --- a/e2e-tests/tests/init-deploy/05-assert.yaml +++ b/e2e-tests/tests/init-deploy/05-assert.yaml @@ -12,7 +12,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.2 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -81,7 +81,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.2 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -144,7 +144,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.2 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/pgbackrest: "" postgres-operator.crunchydata.com/pgbackrest-config: "" @@ -168,7 +168,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.2 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/role: pgbouncer test-label: test @@ -191,7 +191,7 @@ metadata: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.2 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" @@ -214,7 +214,7 @@ spec: app.kubernetes.io/managed-by: percona-postgresql-operator app.kubernetes.io/name: percona-postgresql app.kubernetes.io/part-of: percona-postgresql - pgv2.percona.com/version: 2.8.2 + pgv2.percona.com/version: 2.9.0 postgres-operator.crunchydata.com/cluster: init-deploy postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: "" diff --git a/e2e-tests/tests/upgrade-consistency/01-assert.yaml b/e2e-tests/tests/upgrade-consistency/01-assert.yaml index 60b019bcef..f50e94bdae 100644 --- a/e2e-tests/tests/upgrade-consistency/01-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-assert.yaml @@ -122,7 +122,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.6.0 + crVersion: 2.7.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml index 53c32fbcbe..4cde0661b8 100644 --- a/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/01-create-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.6.0" + cr_version="2.7.0" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ diff --git a/e2e-tests/tests/upgrade-consistency/02-assert.yaml b/e2e-tests/tests/upgrade-consistency/02-assert.yaml index 4bce8de813..45ce641352 100644 --- a/e2e-tests/tests/upgrade-consistency/02-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.7.0 + crVersion: 2.8.2 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index f35c4dd88d..df3042fd07 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.7.0" + cr_version="2.8.2" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ - \ | yq eval ".spec.image=\"${IMAGE_BASE}:pg-operator-$cr_version-ppg$PG_VER-postgres\"" - \ diff --git a/e2e-tests/tests/upgrade-consistency/03-assert.yaml b/e2e-tests/tests/upgrade-consistency/03-assert.yaml index 40ae702403..1382b3ea26 100644 --- a/e2e-tests/tests/upgrade-consistency/03-assert.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-assert.yaml @@ -120,7 +120,7 @@ kind: PerconaPGCluster metadata: name: upgrade-consistency spec: - crVersion: 2.8.2 + crVersion: 2.9.0 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml index 316502decc..39867d5f74 100644 --- a/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/03-patch-cluster.yaml @@ -8,7 +8,7 @@ commands: source ../../functions - cr_version="2.8.2" + cr_version="2.9.0" get_cr \ | yq eval ".spec.crVersion=\"$cr_version\"" - \ | yq eval ".spec.image=\"${IMAGE_BASE}:main-ppg$PG_VER-postgres\"" - \ diff --git a/percona/controller/testdata/sidecar-resources-cr.yaml b/percona/controller/testdata/sidecar-resources-cr.yaml index 1c137a6ead..aa347ddfd9 100644 --- a/percona/controller/testdata/sidecar-resources-cr.yaml +++ b/percona/controller/testdata/sidecar-resources-cr.yaml @@ -4,7 +4,7 @@ kind: PerconaPGCluster metadata: name: cluster1 spec: - crVersion: 2.8.0 + crVersion: 2.9.0 image: perconalab/percona-postgresql-operator:main-ppg17-postgres imagePullPolicy: Always diff --git a/percona/version/version.txt b/percona/version/version.txt index 1817afea41..c8e38b6140 100644 --- a/percona/version/version.txt +++ b/percona/version/version.txt @@ -1 +1 @@ -2.8.2 +2.9.0 From 797077b5407f4055f7221905b0f0f2fb67ff7485 Mon Sep 17 00:00:00 2001 From: Eleonora Zinchenko Date: Mon, 5 Jan 2026 17:35:40 +0200 Subject: [PATCH 239/300] Use 2.8.2 in 02-patch-cluster step --- e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml index d26938bd37..bb49aec3f2 100644 --- a/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml +++ b/e2e-tests/tests/upgrade-consistency/02-patch-cluster.yaml @@ -10,7 +10,7 @@ commands: get_cr \ | yq eval ' - .spec.crVersion="2.8.1"' - \ + .spec.crVersion="2.8.2"' - \ | kubectl -n "${NAMESPACE}" apply -f - sleep 10 From f09002d7d84a6af27a8251b236f0ffe10e5ff2a4 Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Tue, 6 Jan 2026 11:40:14 -0300 Subject: [PATCH 240/300] CLOUD-946 Remove Snyk gh action --- .e2eignore | 1 - .github/workflows/scan.yml | 17 ----------------- .snyk | 10 ---------- 3 files changed, 28 deletions(-) delete mode 100644 .snyk diff --git a/.e2eignore b/.e2eignore index c529743135..0e9d0f0e65 100644 --- a/.e2eignore +++ b/.e2eignore @@ -9,4 +9,3 @@ README.md .gitignore release_versions .e2eignore -.snyk diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 9e8f3274be..539e2a17fe 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -30,14 +30,6 @@ jobs: export DOCKER_DEFAULT_PLATFORM='linux/arm64' make build-docker-image - - name: Run Snyk vulnerability scanner image (linux/arm64) - uses: snyk/actions/docker@master - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - with: - image: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-arm64' - args: --platform=linux/arm64 --severity-threshold=high --exclude-base-image-vulns --file=./build/postgres-operator/Dockerfile -fail-on=upgradable - - name: Build an image from Dockerfile (linux/amd64) run: | export IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64 @@ -45,12 +37,3 @@ jobs: export DOCKER_SQUASH=0 export DOCKER_DEFAULT_PLATFORM='linux/amd64' make build-docker-image - - - name: Run Snyk vulnerability scanner image (linux/amd64) - uses: snyk/actions/docker@master - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} - with: - image: '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}-amd64' - args: --platform=linux/amd64 --severity-threshold=high --exclude-base-image-vulns --file=./build/postgres-operator/Dockerfile -fail-on=upgradable - diff --git a/.snyk b/.snyk deleted file mode 100644 index b0b73b3708..0000000000 --- a/.snyk +++ /dev/null @@ -1,10 +0,0 @@ -#SNYK - percona/percona-postgresql-operator - -exclude: - global: - - e2e-tests/** - - testing/** - -version: v1.25.0 -ignore: {} -patch: {} From 487b2a325da8cdbd3baa7c46e39716364b388183 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 12:47:38 +0000 Subject: [PATCH 241/300] CLOUD-727: Bump golang.org/x/crypto from 0.45.0 to 0.46.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.45.0 to 0.46.0. - [Commits](https://github.com/golang/crypto/compare/v0.45.0...v0.46.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.46.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 3722e71cb2..3b136b8cd8 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.39.0 go.opentelemetry.io/otel/trace v1.39.0 go.uber.org/zap v1.27.1 - golang.org/x/crypto v0.45.0 + golang.org/x/crypto v0.46.0 google.golang.org/grpc v1.77.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.34.2 @@ -124,10 +124,10 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.32.0 // indirect - golang.org/x/sync v0.18.0 // indirect + golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.39.0 // indirect - golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect + golang.org/x/term v0.38.0 // indirect + golang.org/x/text v0.32.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.39.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 8d82e4349e..07f64681ad 100644 --- a/go.sum +++ b/go.sum @@ -289,8 +289,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -310,8 +310,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -324,14 +324,14 @@ golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From a4aaa7883fdffdd2031eef2612112969c0bf6e87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:20:15 +0000 Subject: [PATCH 242/300] CLOUD-727: Bump github.com/onsi/gomega from 1.38.2 to 1.38.3 Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.38.2 to 1.38.3. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.38.2...v1.38.3) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-version: 1.38.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b136b8cd8..17e6b68bab 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 github.com/onsi/ginkgo/v2 v2.27.2 - github.com/onsi/gomega v1.38.2 + github.com/onsi/gomega v1.38.3 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 diff --git a/go.sum b/go.sum index 07f64681ad..41d5441f8d 100644 --- a/go.sum +++ b/go.sum @@ -183,8 +183,8 @@ github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= -github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= -github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM= +github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= From 26c58f5c9888f14a814b303c9ee9e65790161fb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:20:20 +0000 Subject: [PATCH 243/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace](https://github.com/open-telemetry/opentelemetry-go) from 1.38.0 to 1.39.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.38.0...v1.39.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace dependency-version: 1.39.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3b136b8cd8..5e689f62b7 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( go.nhat.io/grpcmock v0.33.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 go.opentelemetry.io/otel v1.39.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 go.opentelemetry.io/otel/sdk v1.39.0 @@ -120,7 +120,7 @@ require ( go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect go.opentelemetry.io/otel/metric v1.39.0 // indirect - go.opentelemetry.io/proto/otlp v1.7.1 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.47.0 // indirect golang.org/x/oauth2 v0.32.0 // indirect diff --git a/go.sum b/go.sum index 07f64681ad..d29fe42942 100644 --- a/go.sum +++ b/go.sum @@ -259,8 +259,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 h1:8UPA4IbVZxpsD76ihGOQiFml99GPAEZLohDXvqHdi6U= @@ -273,8 +273,8 @@ go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2W go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= -go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= -go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= From fa3b2226d576d26584ca04c304b123589b5c0cab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:20:25 +0000 Subject: [PATCH 244/300] CLOUD-727: Bump github.com/go-openapi/errors from 0.22.4 to 0.22.5 Bumps [github.com/go-openapi/errors](https://github.com/go-openapi/errors) from 0.22.4 to 0.22.5. - [Release notes](https://github.com/go-openapi/errors/releases) - [Commits](https://github.com/go-openapi/errors/compare/v0.22.4...v0.22.5) --- updated-dependencies: - dependency-name: github.com/go-openapi/errors dependency-version: 0.22.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b136b8cd8..3f62b53507 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.25.1 require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc github.com/go-logr/logr v1.4.3 - github.com/go-openapi/errors v0.22.4 + github.com/go-openapi/errors v0.22.6 github.com/go-openapi/runtime v0.29.2 github.com/go-openapi/strfmt v0.25.0 github.com/go-openapi/swag v0.25.3 diff --git a/go.sum b/go.sum index 07f64681ad..bb7361070d 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/analysis v0.24.1 h1:Xp+7Yn/KOnVWYG8d+hPksOYnCYImE3TieBa7rBOesYM= github.com/go-openapi/analysis v0.24.1/go.mod h1:dU+qxX7QGU1rl7IYhBC8bIfmWQdX4Buoea4TGtxXY84= -github.com/go-openapi/errors v0.22.4 h1:oi2K9mHTOb5DPW2Zjdzs/NIvwi2N3fARKaTJLdNabaM= -github.com/go-openapi/errors v0.22.4/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= +github.com/go-openapi/errors v0.22.6 h1:eDxcf89O8odEnohIXwEjY1IB4ph5vmbUsBMsFNwXWPo= +github.com/go-openapi/errors v0.22.6/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk= github.com/go-openapi/jsonpointer v0.22.1 h1:sHYI1He3b9NqJ4wXLoJDKmUmHkWy/L7rtEo92JUxBNk= github.com/go-openapi/jsonpointer v0.22.1/go.mod h1:pQT9OsLkfz1yWoMgYFy4x3U5GY5nUlsOn1qSBH5MkCM= github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc= From 591eb8d7221cf1134bdfa65bfd2901510ce75d7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 09:45:58 +0000 Subject: [PATCH 245/300] CLOUD-727: Bump sigs.k8s.io/controller-runtime from 0.21.0 to 0.22.1 Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.21.0 to 0.22.1. - [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.21.0...v0.22.1) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-runtime dependency-version: 0.22.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0e865b5e25..13d44d7fc5 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( k8s.io/apimachinery v0.34.2 k8s.io/client-go v0.34.2 k8s.io/component-base v0.34.2 - sigs.k8s.io/controller-runtime v0.21.0 + sigs.k8s.io/controller-runtime v0.22.4 sigs.k8s.io/yaml v1.6.0 ) diff --git a/go.sum b/go.sum index 2aadacbe35..4b9c114d90 100644 --- a/go.sum +++ b/go.sum @@ -394,8 +394,8 @@ k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOP k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8= -sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM= +sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A= +sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= From defdd506866e704ffceae3006ba0b091b9340c90 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 8 Jan 2026 12:06:17 +0200 Subject: [PATCH 246/300] fix --- internal/controller/runtime/client.go | 7 +++++++ internal/controller/runtime/pod_client.go | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/controller/runtime/client.go b/internal/controller/runtime/client.go index 4cc05c9835..642b265074 100644 --- a/internal/controller/runtime/client.go +++ b/internal/controller/runtime/client.go @@ -7,6 +7,7 @@ package runtime import ( "context" + "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -31,6 +32,7 @@ type ( ClientPatch func(context.Context, client.Object, client.Patch, ...client.PatchOption) error ClientDeleteAll func(context.Context, client.Object, ...client.DeleteAllOfOption) error ClientUpdate func(context.Context, client.Object, ...client.UpdateOption) error + ClientApply func(context.Context, runtime.ApplyConfiguration, ...client.ApplyOption) error ) // ClientWriter implements [client.Writer] by composing assignable functions. @@ -40,6 +42,7 @@ type ClientWriter struct { ClientDeleteAll ClientPatch ClientUpdate + ClientApply } var _ client.Writer = ClientWriter{} @@ -74,3 +77,7 @@ func (fn ClientPatch) Patch(ctx context.Context, obj client.Object, patch client func (fn ClientUpdate) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { return fn(ctx, obj, opts...) } + +func (fn ClientApply) Apply(ctx context.Context, obj runtime.ApplyConfiguration, opts ...client.ApplyOption) error { + return fn(ctx, obj, opts...) +} diff --git a/internal/controller/runtime/pod_client.go b/internal/controller/runtime/pod_client.go index 597de85a24..444b17d6ba 100644 --- a/internal/controller/runtime/pod_client.go +++ b/internal/controller/runtime/pod_client.go @@ -32,7 +32,7 @@ func newPodClient(config *rest.Config) (rest.Interface, error) { if err != nil { return nil, err } - return apiutil.RESTClientForGVK(gvk, false, config, codecs, httpClient) + return apiutil.RESTClientForGVK(gvk, false, false, config, codecs, httpClient) } // +kubebuilder:rbac:groups="",resources="pods/exec",verbs={create} From 8c4ff8b72900fee5097f9e5985f5828112012b5c Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 8 Jan 2026 13:35:41 +0200 Subject: [PATCH 247/300] fix weird bug --- pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go index 023a1b7fb9..15c4433251 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go @@ -105,6 +105,13 @@ func (PITRestoreDateTime) OpenAPISchemaType() []string { return []string{"string func (PITRestoreDateTime) OpenAPISchemaFormat() string { return "" } +func (t *PITRestoreDateTime) ToUnstructured() any { + if t.IsZero() { + return nil + } + return t.Time.ToUnstructured() +} + func (t *PITRestoreDateTime) UnmarshalJSON(b []byte) (err error) { if len(b) == 4 && string(b) == "null" { mt := metav1.NewTime(time.Time{}) From 3450cd35795359a418fa70a6e9d0f503d3301746 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 8 Jan 2026 13:43:38 +0200 Subject: [PATCH 248/300] update deps --- go.mod | 31 +++++++++++----------- go.sum | 81 ++++++++++++++++++++++------------------------------------ 2 files changed, 45 insertions(+), 67 deletions(-) diff --git a/go.mod b/go.mod index 13d44d7fc5..8728ac2855 100644 --- a/go.mod +++ b/go.mod @@ -32,10 +32,11 @@ require ( golang.org/x/crypto v0.46.0 google.golang.org/grpc v1.77.0 gotest.tools/v3 v3.5.2 - k8s.io/api v0.34.2 - k8s.io/apimachinery v0.34.2 - k8s.io/client-go v0.34.2 - k8s.io/component-base v0.34.2 + k8s.io/api v0.35.0 + k8s.io/apiextensions-apiserver v0.35.0 + k8s.io/apimachinery v0.35.0 + k8s.io/client-go v0.35.0 + k8s.io/component-base v0.35.0 sigs.k8s.io/controller-runtime v0.22.4 sigs.k8s.io/yaml v1.6.0 ) @@ -65,10 +66,10 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/mod v0.30.0 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) @@ -89,7 +90,6 @@ require ( github.com/go-openapi/jsonreference v0.21.3 // indirect github.com/go-openapi/loads v0.23.2 // indirect github.com/go-openapi/spec v0.22.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.7.0 // indirect @@ -104,14 +104,14 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/robfig/cron/v3 v3.0.1 github.com/sergi/go-diff v1.4.0 // indirect github.com/spf13/afero v1.15.0 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.9 // indirect github.com/stretchr/testify v1.11.1 github.com/swaggest/assertjson v1.9.0 // indirect github.com/yudai/gojsondiff v1.0.0 // indirect @@ -136,9 +136,8 @@ require ( google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.34.2 k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect ) diff --git a/go.sum b/go.sum index 4b9c114d90..82cdd3bc5a 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,6 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -140,8 +138,6 @@ github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -192,14 +188,14 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -210,8 +206,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= @@ -240,8 +236,6 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3Ifn github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= @@ -281,25 +275,18 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= +go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= @@ -307,14 +294,10 @@ golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -336,15 +319,11 @@ golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= @@ -363,8 +342,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= +gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -378,26 +357,26 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY= -k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw= -k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo= -k8s.io/apiextensions-apiserver v0.34.2/go.mod h1:398CJrsgXF1wytdaanynDpJ67zG4Xq7yj91GrmYN2SE= -k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4= -k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw= -k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M= -k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE= -k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ= -k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM= +k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY= +k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA= +k8s.io/apiextensions-apiserver v0.35.0 h1:3xHk2rTOdWXXJM+RDQZJvdx0yEOgC0FgQ1PlJatA5T4= +k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU= +k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8= +k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE= +k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o= +k8s.io/component-base v0.35.0 h1:+yBrOhzri2S1BVqyVSvcM3PtPyx5GUxCK2tinZz1G94= +k8s.io/component-base v0.35.0/go.mod h1:85SCX4UCa6SCFt6p3IKAPej7jSnF3L8EbfSyMZayJR0= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA= -k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= +k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= +k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A= sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= -sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= From 3c66aa2fac0f7a6db97429782d8cf8209b3018fe Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 8 Jan 2026 13:50:00 +0200 Subject: [PATCH 249/300] update envtest version --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 81054da730..524308b9bf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,4 +15,4 @@ jobs: - name: Basic tests run: make check - name: envtest - run: ENVTEST_K8S_VERSION=1.32 make check-envtest + run: ENVTEST_K8S_VERSION=1.35 make check-envtest From a532b7e1298896abec6e33aead99a9b1bbfc8c89 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 8 Jan 2026 13:51:04 +0200 Subject: [PATCH 250/300] `make manifests` and update `controller-gen` --- ...ator.crunchydata.com_postgresclusters.yaml | 171 +++++++-- .../pgv2.percona.com_perconapgbackups.yaml | 4 +- .../pgv2.percona.com_perconapgclusters.yaml | 112 ++++-- .../pgv2.percona.com_perconapgrestores.yaml | 2 +- .../pgv2.percona.com_perconapgupgrades.yaml | 9 +- .../pgv2.percona.com_perconapgclusters.yaml | 127 +++++-- ...crunchydata.com_crunchybridgeclusters.yaml | 2 +- ...res-operator.crunchydata.com_pgadmins.yaml | 25 +- ...s-operator.crunchydata.com_pgupgrades.yaml | 9 +- ...ator.crunchydata.com_postgresclusters.yaml | 171 +++++++-- deploy/bundle.yaml | 334 +++++++++++++++--- deploy/crd.yaml | 334 +++++++++++++++--- deploy/cw-bundle.yaml | 334 +++++++++++++++--- hack/controller-generator.sh | 2 +- 14 files changed, 1367 insertions(+), 269 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 02169bbf8a..5c929ad783 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: postgresclusters.postgres-operator.crunchydata.com spec: group: postgres-operator.crunchydata.com @@ -386,6 +386,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -2231,9 +2249,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -4425,7 +4444,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -5223,9 +5244,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -5600,7 +5622,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -6769,9 +6791,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -7275,6 +7298,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -8835,6 +8876,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -9125,7 +9184,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -9323,9 +9382,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10391,9 +10451,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10461,9 +10522,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10528,9 +10590,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10596,9 +10659,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -12767,7 +12831,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -13514,7 +13580,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -14969,7 +15035,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -16128,7 +16196,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -16271,9 +16339,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -16625,7 +16694,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -17104,6 +17173,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -18726,6 +18813,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -19716,7 +19821,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -21137,9 +21244,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -22783,6 +22891,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -23002,7 +23128,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -23282,9 +23408,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml index b3989160e7..f9aaf1c422 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -280,7 +280,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index e89804051b..85a7b5717e 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -410,6 +410,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -2389,9 +2407,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -4583,7 +4602,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -5381,9 +5402,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -5758,7 +5780,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -6926,9 +6948,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -8377,6 +8400,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -8667,7 +8708,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -8865,9 +8906,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -9933,9 +9975,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10003,9 +10046,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10070,9 +10114,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10138,9 +10183,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -11769,7 +11815,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -13222,7 +13268,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -15088,7 +15136,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -15845,7 +15895,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -15988,9 +16038,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -16342,7 +16393,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -18158,6 +18209,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -19872,7 +19941,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -20551,9 +20622,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml index 0a0f2cc39f..e1bc4d36b7 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml index b065955532..39f6faab10 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgupgrades.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -1861,7 +1861,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -2630,9 +2632,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 63f540edd2..8af487e0fd 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgbackups.pgv2.percona.com spec: group: pgv2.percona.com @@ -279,7 +279,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -408,7 +408,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgclusters.pgv2.percona.com spec: group: pgv2.percona.com @@ -815,6 +815,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -2794,9 +2812,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -4988,7 +5007,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -5786,9 +5807,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -6163,7 +6185,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -7331,9 +7353,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -8782,6 +8805,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -9072,7 +9113,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -9270,9 +9311,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10338,9 +10380,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10408,9 +10451,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10475,9 +10519,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10543,9 +10588,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -12174,7 +12220,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -13627,7 +13673,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -15493,7 +15541,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -16250,7 +16300,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -16393,9 +16443,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -16747,7 +16798,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -18563,6 +18614,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -20277,7 +20346,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -20956,9 +21027,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -21810,7 +21882,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgrestores.pgv2.percona.com spec: group: pgv2.percona.com @@ -21908,7 +21980,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 name: perconapgupgrades.pgv2.percona.com spec: group: pgv2.percona.com @@ -23766,7 +23838,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -24535,9 +24609,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml index cbbca84540..19b65d0271 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml index 86feaf6aff..0602093448 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -1311,6 +1311,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -1526,7 +1544,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -1842,9 +1860,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml index ead8e93bc9..828b9583c7 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -1859,7 +1859,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -2624,9 +2626,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index c7f7cedf8f..1275e6a397 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -383,6 +383,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -2223,9 +2241,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -4417,7 +4436,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -5205,9 +5226,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -5583,7 +5605,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -6759,9 +6781,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -7260,6 +7283,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -8800,6 +8841,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -9085,7 +9144,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -9283,9 +9342,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10351,9 +10411,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10421,9 +10482,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10488,9 +10550,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10556,9 +10619,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -12702,7 +12766,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -13449,7 +13515,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -14911,7 +14977,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -16070,7 +16138,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -16213,9 +16281,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -16568,7 +16637,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -17050,6 +17119,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -18664,6 +18751,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -19630,7 +19735,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -21046,9 +21153,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -22690,6 +22798,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -22900,7 +23026,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -23180,9 +23306,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 1dda0baea3..aa2c93d8bd 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com @@ -574,7 +574,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com @@ -1112,6 +1112,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -3091,9 +3109,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -5285,7 +5304,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -6083,9 +6104,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -6460,7 +6482,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -7628,9 +7650,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -9079,6 +9102,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -9369,7 +9410,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -9567,9 +9608,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10635,9 +10677,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10705,9 +10748,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10772,9 +10816,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10840,9 +10885,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -12471,7 +12517,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -13924,7 +13970,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -15790,7 +15838,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -16547,7 +16597,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -16690,9 +16740,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -17044,7 +17095,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -18860,6 +18911,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -20574,7 +20643,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -21253,9 +21324,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -22107,7 +22179,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22279,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com @@ -24067,7 +24139,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -24836,9 +24910,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -25011,7 +25086,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -26320,6 +26395,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -26535,7 +26628,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -26851,9 +26944,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -27010,7 +27104,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -28867,7 +28961,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -29632,9 +29728,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -29801,7 +29898,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -30182,6 +30279,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -32022,9 +32137,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -34216,7 +34332,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -35004,9 +35122,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -35382,7 +35501,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -36558,9 +36677,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -37059,6 +37179,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -38599,6 +38737,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -38884,7 +39040,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -39082,9 +39238,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40150,9 +40307,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40220,9 +40378,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40287,9 +40446,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40355,9 +40515,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -42501,7 +42662,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -43248,7 +43411,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -44710,7 +44873,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -45869,7 +46034,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -46012,9 +46177,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -46367,7 +46533,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -46849,6 +47015,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -48463,6 +48647,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -49429,7 +49631,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -50845,9 +51049,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -52489,6 +52694,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -52699,7 +52922,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -52979,9 +53202,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/deploy/crd.yaml b/deploy/crd.yaml index f6f316458f..68b8a5788f 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com @@ -574,7 +574,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com @@ -1112,6 +1112,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -3091,9 +3109,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -5285,7 +5304,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -6083,9 +6104,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -6460,7 +6482,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -7628,9 +7650,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -9079,6 +9102,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -9369,7 +9410,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -9567,9 +9608,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10635,9 +10677,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10705,9 +10748,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10772,9 +10816,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10840,9 +10885,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -12471,7 +12517,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -13924,7 +13970,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -15790,7 +15838,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -16547,7 +16597,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -16690,9 +16740,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -17044,7 +17095,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -18860,6 +18911,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -20574,7 +20643,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -21253,9 +21324,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -22107,7 +22179,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22279,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com @@ -24067,7 +24139,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -24836,9 +24910,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -25011,7 +25086,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -26320,6 +26395,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -26535,7 +26628,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -26851,9 +26944,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -27010,7 +27104,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -28867,7 +28961,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -29632,9 +29728,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -29801,7 +29898,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -30182,6 +30279,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -32022,9 +32137,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -34216,7 +34332,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -35004,9 +35122,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -35382,7 +35501,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -36558,9 +36677,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -37059,6 +37179,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -38599,6 +38737,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -38884,7 +39040,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -39082,9 +39238,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40150,9 +40307,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40220,9 +40378,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40287,9 +40446,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40355,9 +40515,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -42501,7 +42662,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -43248,7 +43411,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -44710,7 +44873,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -45869,7 +46034,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -46012,9 +46177,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -46367,7 +46533,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -46849,6 +47015,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -48463,6 +48647,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -49429,7 +49631,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -50845,9 +51049,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -52489,6 +52694,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -52699,7 +52922,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -52979,9 +53202,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index d339592195..7c5c730043 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -295,7 +295,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgbackups.pgv2.percona.com @@ -574,7 +574,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -703,7 +703,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgclusters.pgv2.percona.com @@ -1112,6 +1112,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -3091,9 +3109,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -5285,7 +5304,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -6083,9 +6104,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -6460,7 +6482,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -7628,9 +7650,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -9079,6 +9102,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -9369,7 +9410,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -9567,9 +9608,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10635,9 +10677,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10705,9 +10748,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10772,9 +10816,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -10840,9 +10885,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -12471,7 +12517,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -13924,7 +13970,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -15790,7 +15838,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -16547,7 +16597,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -16690,9 +16740,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -17044,7 +17095,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -18860,6 +18911,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -20574,7 +20643,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -21253,9 +21324,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -22107,7 +22179,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgrestores.pgv2.percona.com @@ -22207,7 +22279,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: pgv2.percona.com/version: v2.9.0 name: perconapgupgrades.pgv2.percona.com @@ -24067,7 +24139,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -24836,9 +24910,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -25011,7 +25086,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -26320,6 +26395,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -26535,7 +26628,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -26851,9 +26944,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -27010,7 +27104,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -28867,7 +28961,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -29632,9 +29728,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -29801,7 +29898,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.18.0 + controller-gen.kubebuilder.io/version: v0.20.0 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: 5.4.2 @@ -30182,6 +30279,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -32022,9 +32137,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -34216,7 +34332,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -35004,9 +35122,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -35382,7 +35501,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -36558,9 +36677,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -37059,6 +37179,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -38599,6 +38737,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -38884,7 +39040,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -39082,9 +39238,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40150,9 +40307,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40220,9 +40378,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40287,9 +40446,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -40355,9 +40515,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -42501,7 +42662,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -43248,7 +43411,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -44710,7 +44873,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -45869,7 +46034,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -46012,9 +46177,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -46367,7 +46533,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -46849,6 +47015,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -48463,6 +48647,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -49429,7 +49631,9 @@ spec: type: integer type: object resizePolicy: - description: Resources resize policy for the container. + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. items: description: ContainerResizePolicy represents resource resize policy for the container. @@ -50845,9 +51049,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- @@ -52489,6 +52694,24 @@ spec: description: Kubelet's generated CSRs will be addressed to this signer. type: string + userAnnotations: + additionalProperties: + type: string + description: |- + userAnnotations allow pod authors to pass additional information to + the signer implementation. Kubernetes does not restrict or validate this + metadata in any way. + + These values are copied verbatim into the `spec.unverifiedUserAnnotations` field of + the PodCertificateRequest objects that Kubelet creates. + + Entries are subject to the same validation as object metadata annotations, + with the addition that all keys must be domain-prefixed. No restrictions + are placed on values, except an overall size limitation on the entire field. + + Signers should document the keys and values they support. Signers should + deny requests that contain keys they do not recognize. + type: object required: - keyType - signerName @@ -52699,7 +52922,7 @@ spec: resources: description: |- resources represents the minimum resources the volume should have. - If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements + Users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources @@ -52979,9 +53202,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. Exists is equivalent to wildcard for value, so that a pod can tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). type: string tolerationSeconds: description: |- diff --git a/hack/controller-generator.sh b/hack/controller-generator.sh index 0c492c3a1b..7d4edbd704 100755 --- a/hack/controller-generator.sh +++ b/hack/controller-generator.sh @@ -22,6 +22,6 @@ set -eu # Find `controller-gen` on the current PATH or install it to the Go install path. tool="$(command -v controller-gen || true)" [ -n "$tool" ] || tool="$GOBIN/controller-gen" -[ -x "$tool" ] || go install 'sigs.k8s.io/controller-tools/cmd/controller-gen@v0.18.0' +[ -x "$tool" ] || go install 'sigs.k8s.io/controller-tools/cmd/controller-gen@v0.20.0' "$tool" "$@" From c4f8ced93235529c081faadd9872a4acf3a84425 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 8 Jan 2026 14:07:08 +0200 Subject: [PATCH 251/300] fix unit-tests --- .../controller/postgrescluster/apply_test.go | 6 + .../controller_ref_manager_test.go | 12 +- .../postgrescluster/pgbackrest_test.go | 232 +++++++++++------- .../standalone_pgadmin/statefulset_test.go | 7 +- 4 files changed, 160 insertions(+), 97 deletions(-) diff --git a/internal/controller/postgrescluster/apply_test.go b/internal/controller/postgrescluster/apply_test.go index b7e788c2ce..341a754b02 100644 --- a/internal/controller/postgrescluster/apply_test.go +++ b/internal/controller/postgrescluster/apply_test.go @@ -151,6 +151,12 @@ func TestServerSideApply(t *testing.T) { MatchLabels: map[string]string{"select": name}, } sts.Spec.Template.Labels = map[string]string{"select": name} + sts.Spec.Template.Spec.Containers = []corev1.Container{ + { + Name: "some-container", + Image: "some-image", + }, + } return &sts } diff --git a/internal/controller/postgrescluster/controller_ref_manager_test.go b/internal/controller/postgrescluster/controller_ref_manager_test.go index 10d5c0798e..4781ff6bb5 100644 --- a/internal/controller/postgrescluster/controller_ref_manager_test.go +++ b/internal/controller/postgrescluster/controller_ref_manager_test.go @@ -46,12 +46,19 @@ func TestManageControllerRefs(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"label1": "val1"}, }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "some-name", + Image: "some-image", + }, + }, + }, }, }, } t.Run("adopt Object", func(t *testing.T) { - obj := objBase.DeepCopy() obj.Name = "adopt" obj.Labels = map[string]string{naming.LabelCluster: clusterName} @@ -84,7 +91,6 @@ func TestManageControllerRefs(t *testing.T) { }) t.Run("release Object", func(t *testing.T) { - isTrue := true obj := objBase.DeepCopy() obj.Name = "release" @@ -115,7 +121,6 @@ func TestManageControllerRefs(t *testing.T) { }) t.Run("ignore Object: no matching labels or owner refs", func(t *testing.T) { - obj := objBase.DeepCopy() obj.Name = "ignore-no-labels-refs" obj.Labels = map[string]string{"ignore-label": "ignore-value"} @@ -138,7 +143,6 @@ func TestManageControllerRefs(t *testing.T) { }) t.Run("ignore Object: PostgresCluster does not exist", func(t *testing.T) { - obj := objBase.DeepCopy() obj.Name = "ignore-no-postgrescluster" obj.Labels = map[string]string{naming.LabelCluster: "nonexistent"} diff --git a/internal/controller/postgrescluster/pgbackrest_test.go b/internal/controller/postgrescluster/pgbackrest_test.go index 8d345b38ef..dfcc047584 100644 --- a/internal/controller/postgrescluster/pgbackrest_test.go +++ b/internal/controller/postgrescluster/pgbackrest_test.go @@ -50,7 +50,8 @@ import ( var testCronSchedule string = "*/15 * * * *" func fakePostgresCluster(clusterName, namespace, clusterUID string, - includeDedicatedRepo bool) *v1beta1.PostgresCluster { + includeDedicatedRepo bool, +) *v1beta1.PostgresCluster { postgresCluster := &v1beta1.PostgresCluster{ ObjectMeta: metav1.ObjectMeta{ Name: clusterName, @@ -90,8 +91,10 @@ func fakePostgresCluster(clusterName, namespace, clusterUID string, Jobs: &v1beta1.BackupJobs{ PriorityClassName: initialize.String("some-priority-class"), }, - Global: map[string]string{"repo2-test": "config", - "repo3-test": "config", "repo4-test": "config"}, + Global: map[string]string{ + "repo2-test": "config", + "repo3-test": "config", "repo4-test": "config", + }, Repos: []v1beta1.PGBackRestRepo{{ Name: "repo1", S3: &v1beta1.RepoS3{ @@ -173,7 +176,9 @@ func fakeObservedCronJobs() []*batchv1.CronJob { { ObjectMeta: metav1.ObjectMeta{ Name: "fake-cronjob", - }}} + }, + }, + } } func TestReconcilePGBackRest(t *testing.T) { @@ -211,7 +216,8 @@ func TestReconcilePGBackRest(t *testing.T) { // create the 'observed' instances and set the leader instances := &observedInstances{ - forCluster: []*Instance{{Name: "instance1", + forCluster: []*Instance{{ + Name: "instance1", Pods: []*corev1.Pod{{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{naming.LabelRole: naming.RolePatroniLeader}, @@ -226,7 +232,8 @@ func TestReconcilePGBackRest(t *testing.T) { Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ RepoHost: &v1beta1.RepoHostStatus{Ready: true}, - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, } // set conditions @@ -236,7 +243,8 @@ func TestReconcilePGBackRest(t *testing.T) { } for condition, status := range clusterConditions { meta.SetStatusCondition(&postgresCluster.Status.Conditions, metav1.Condition{ - Type: condition, Reason: "testing", Status: status}) + Type: condition, Reason: "testing", Status: status, + }) } rootCA, err := pki.NewRootCertificateAuthority() @@ -252,7 +260,6 @@ func TestReconcilePGBackRest(t *testing.T) { // test that the repo was created properly t.Run("verify pgbackrest dedicated repo StatefulSet", func(t *testing.T) { - // get the pgBackRest repo sts using the labels we expect it to have dedicatedRepos := &appsv1.StatefulSetList{} if err := tClient.List(ctx, dedicatedRepos, client.InNamespace(ns.Name), @@ -432,7 +439,6 @@ topologySpreadConstraints: }) t.Run("verify pgbackrest repo volumes", func(t *testing.T) { - // get the pgBackRest repo sts using the labels we expect it to have repoVols := &corev1.PersistentVolumeClaimList{} if err := tClient.List(ctx, repoVols, client.InNamespace(ns.Name), @@ -462,7 +468,6 @@ topologySpreadConstraints: }) t.Run("verify pgbackrest configuration", func(t *testing.T) { - config := &corev1.ConfigMap{} if err := tClient.Get(ctx, types.NamespacedName{ Name: naming.PGBackRestConfig(postgresCluster).Name, @@ -487,12 +492,12 @@ topologySpreadConstraints: }) t.Run("verify pgbackrest schedule cronjob", func(t *testing.T) { - // set status postgresCluster.Status = v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, } // set conditions @@ -503,7 +508,8 @@ topologySpreadConstraints: for condition, status := range clusterConditions { meta.SetStatusCondition(&postgresCluster.Status.Conditions, metav1.Condition{ - Type: condition, Reason: "testing", Status: status}) + Type: condition, Reason: "testing", Status: status, + }) } requeue := r.reconcileScheduledBackups(ctx, postgresCluster, serviceAccount, fakeObservedCronJobs()) @@ -524,11 +530,9 @@ topologySpreadConstraints: assert.Equal(t, returnedCronJob.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Name, "pgbackrest") assert.Assert(t, returnedCronJob.Spec.JobTemplate.Spec.Template.Spec.Containers[0].SecurityContext != &corev1.SecurityContext{}) - }) t.Run("verify pgbackrest schedule found", func(t *testing.T) { - assert.Assert(t, backupScheduleFound(repo, "full")) testrepo := v1beta1.PGBackRestRepo{ @@ -537,25 +541,22 @@ topologySpreadConstraints: Full: &testCronSchedule, Differential: &testCronSchedule, Incremental: &testCronSchedule, - }} + }, + } assert.Assert(t, backupScheduleFound(testrepo, "full")) assert.Assert(t, backupScheduleFound(testrepo, "diff")) assert.Assert(t, backupScheduleFound(testrepo, "incr")) - }) t.Run("verify pgbackrest schedule not found", func(t *testing.T) { - assert.Assert(t, !backupScheduleFound(repo, "notabackuptype")) noscheduletestrepo := v1beta1.PGBackRestRepo{Name: "repo1"} assert.Assert(t, !backupScheduleFound(noscheduletestrepo, "full")) - }) t.Run("pgbackrest schedule suspended status", func(t *testing.T) { - returnedCronJob := &batchv1.CronJob{} if err := tClient.Get(ctx, types.NamespacedName{ Name: postgresCluster.Name + "-repo1-full", @@ -615,7 +616,8 @@ topologySpreadConstraints: // create the 'observed' instances and set the leader instances := &observedInstances{ - forCluster: []*Instance{{Name: "instance1", + forCluster: []*Instance{{ + Name: "instance1", Pods: []*corev1.Pod{{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{naming.LabelRole: naming.RolePatroniLeader}, @@ -635,7 +637,6 @@ topologySpreadConstraints: assert.Equal(t, result, reconcile.Result{}) t.Run("verify pgbackrest dedicated repo StatefulSet", func(t *testing.T) { - // Verify the sts doesn't exist dedicatedRepos := &appsv1.StatefulSetList{} if err := tClient.List(ctx, dedicatedRepos, client.InNamespace(ns.Name), @@ -651,7 +652,6 @@ topologySpreadConstraints: }) t.Run("verify pgbackrest repo volumes", func(t *testing.T) { - // get the pgBackRest repo sts using the labels we expect it to have repoVols := &corev1.PersistentVolumeClaimList{} if err := tClient.List(ctx, repoVols, client.InNamespace(ns.Name), @@ -667,7 +667,6 @@ topologySpreadConstraints: }) t.Run("verify pgbackrest configuration", func(t *testing.T) { - config := &corev1.ConfigMap{} err := tClient.Get(ctx, types.NamespacedName{ Name: naming.PGBackRestConfig(postgresCluster).Name, @@ -776,12 +775,14 @@ func TestReconcileStanzaCreate(t *testing.T) { }}) stanzaCreateFail := func(ctx context.Context, namespace, pod, container string, stdin io.Reader, - stdout, stderr io.Writer, command ...string) error { + stdout, stderr io.Writer, command ...string, + ) error { return errors.New("fake stanza create failed") } stanzaCreateSuccess := func(ctx context.Context, namespace, pod, container string, stdin io.Reader, - stdout, stderr io.Writer, command ...string) error { + stdout, stderr io.Writer, command ...string, + ) error { return nil } @@ -1105,7 +1106,8 @@ func TestReconcileManualBackup(t *testing.T) { standby: true, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1117,7 +1119,8 @@ func TestReconcileManualBackup(t *testing.T) { clusterConditions: map[string]metav1.ConditionStatus{}, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1132,7 +1135,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1146,7 +1150,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1162,7 +1167,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1177,7 +1183,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1192,7 +1199,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: nil, @@ -1208,8 +1216,10 @@ func TestReconcileManualBackup(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ ManualBackup: &v1beta1.PGBackRestJobStatus{ - ID: backupId, Finished: true}, - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + ID: backupId, Finished: true, + }, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: nil, @@ -1224,7 +1234,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: "", manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1239,7 +1250,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{}}, + Repos: []v1beta1.RepoStatus{}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1255,7 +1267,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1270,7 +1283,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: defaultBackupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1285,7 +1299,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1301,7 +1316,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1317,7 +1333,8 @@ func TestReconcileManualBackup(t *testing.T) { }, status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, backupId: backupId, manual: &v1beta1.PGBackRestManualBackup{RepoName: "repo1"}, @@ -1335,7 +1352,6 @@ func TestReconcileManualBackup(t *testing.T) { clusterName = "manual-backup-" + strconv.Itoa(i) } t.Run(tc.testDesc, func(t *testing.T) { - if tc.dedicatedOnly && !dedicated { t.Skip() } @@ -1350,7 +1366,8 @@ func TestReconcileManualBackup(t *testing.T) { postgresCluster.Status = *tc.status for condition, status := range tc.clusterConditions { meta.SetStatusCondition(&postgresCluster.Status.Conditions, metav1.Condition{ - Type: condition, Reason: "testing", Status: status}) + Type: condition, Reason: "testing", Status: status, + }) } assert.NilError(t, tClient.Status().Update(ctx, postgresCluster)) @@ -1652,7 +1669,14 @@ func TestGetPGBackRestResources(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Labels: naming.PGBackRestDedicatedLabels(clusterName), }, - Spec: corev1.PodSpec{}, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "some-container", + Image: "some-image", + }, + }, + }, }, }, }, @@ -1690,7 +1714,14 @@ func TestGetPGBackRestResources(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Labels: naming.PGBackRestDedicatedLabels(clusterName), }, - Spec: corev1.PodSpec{}, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "some-container", + Image: "some-image", + }, + }, + }, }, }, }, @@ -1899,7 +1930,6 @@ func TestReconcilePostgresClusterDataSource(t *testing.T) { tc.desc += "-no-repo" } t.Run(tc.desc, func(t *testing.T) { - clusterName := "hippocluster-" + strconv.Itoa(i) if !dedicated { clusterName = clusterName + "-no-repo" @@ -2125,7 +2155,6 @@ func TestReconcileCloudBasedDataSource(t *testing.T) { for i, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - clusterName := "hippocluster-" + strconv.Itoa(i) if !dedicated { clusterName = clusterName + "-no-repo" @@ -2259,17 +2288,20 @@ func TestCopyConfigurationResources(t *testing.T) { }}, Backups: v1beta1.Backups{ PGBackRest: v1beta1.PGBackRestArchive{ - Configuration: []corev1.VolumeProjection{{ - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "source-secret" + testNum, + Configuration: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "source-secret" + testNum, + }, }, - }}, { - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "source-configmap" + testNum, + }, { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "source-configmap" + testNum, + }, }, - }}, + }, }, Image: "example.com/crunchy-pgbackrest:test", Repos: []v1beta1.PGBackRestRepo{{ @@ -2605,7 +2637,8 @@ volumes: corev1.ResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("1m"), - }}, + }, + }, ) }) }) @@ -3135,7 +3168,6 @@ func TestObserveRestoreEnv(t *testing.T) { namespace := setupNamespace(t, tClient).Name generateJob := func(clusterName string, completed, failed *bool) *batchv1.Job { - cluster := &v1beta1.PostgresCluster{ ObjectMeta: metav1.ObjectMeta{ Name: clusterName, @@ -3334,7 +3366,6 @@ func TestObserveRestoreEnv(t *testing.T) { for i, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - clusterName := "observe-restore-env" + strconv.Itoa(i) if !dedicated { clusterName = clusterName + "-no-repo" @@ -3372,7 +3403,6 @@ func TestPrepareForRestore(t *testing.T) { namespace := setupNamespace(t, tClient).Name generateJob := func(clusterName string) *batchv1.Job { - cluster := &v1beta1.PostgresCluster{ ObjectMeta: metav1.ObjectMeta{ Name: clusterName, @@ -3423,7 +3453,8 @@ func TestPrepareForRestore(t *testing.T) { }{{ desc: "remove restore jobs", createResources: func(t *testing.T, - cluster *v1beta1.PostgresCluster) (*batchv1.Job, []corev1.Endpoints) { + cluster *v1beta1.PostgresCluster, + ) (*batchv1.Job, []corev1.Endpoints) { job := generateJob(cluster.Name) assert.NilError(t, r.Client.Create(ctx, job)) return job, nil @@ -3441,7 +3472,8 @@ func TestPrepareForRestore(t *testing.T) { }, { desc: "remove patroni endpoints", createResources: func(t *testing.T, - cluster *v1beta1.PostgresCluster) (*batchv1.Job, []corev1.Endpoints) { + cluster *v1beta1.PostgresCluster, + ) (*batchv1.Job, []corev1.Endpoints) { fakeLeaderEP := corev1.Endpoints{} fakeLeaderEP.ObjectMeta = naming.PatroniLeaderEndpoints(cluster) fakeLeaderEP.ObjectMeta.Namespace = namespace @@ -3469,7 +3501,8 @@ func TestPrepareForRestore(t *testing.T) { }, { desc: "cluster fully prepared", createResources: func(t *testing.T, - cluster *v1beta1.PostgresCluster) (*batchv1.Job, []corev1.Endpoints) { + cluster *v1beta1.PostgresCluster, + ) (*batchv1.Job, []corev1.Endpoints) { return nil, []corev1.Endpoints{} }, result: testResult{ @@ -3484,17 +3517,20 @@ func TestPrepareForRestore(t *testing.T) { }, }, { desc: "primary as startup instance", - fakeObserved: &observedInstances{forCluster: []*Instance{{ - Name: primaryInstanceName, - Spec: &v1beta1.PostgresInstanceSetSpec{Name: primaryInstanceSetName}, - Pods: []*corev1.Pod{{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{naming.LabelRole: naming.RolePatroniLeader}, - }, - }}}, + fakeObserved: &observedInstances{forCluster: []*Instance{ + { + Name: primaryInstanceName, + Spec: &v1beta1.PostgresInstanceSetSpec{Name: primaryInstanceSetName}, + Pods: []*corev1.Pod{{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{naming.LabelRole: naming.RolePatroniLeader}, + }, + }}, + }, }}, createResources: func(t *testing.T, - cluster *v1beta1.PostgresCluster) (*batchv1.Job, []corev1.Endpoints) { + cluster *v1beta1.PostgresCluster, + ) (*batchv1.Job, []corev1.Endpoints) { return nil, []corev1.Endpoints{} }, result: testResult{ @@ -3515,7 +3551,6 @@ func TestPrepareForRestore(t *testing.T) { name = tc.desc + "-no-repo" } t.Run(name, func(t *testing.T) { - clusterName := "prepare-for-restore-" + strconv.Itoa(i) if !dedicated { clusterName = clusterName + "-no-repo" @@ -3659,7 +3694,8 @@ func TestReconcileScheduledBackups(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, expectReconcile: true, expectRequeue: false, @@ -3672,7 +3708,8 @@ func TestReconcileScheduledBackups(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, expectReconcile: true, expectRequeue: false, @@ -3681,7 +3718,8 @@ func TestReconcileScheduledBackups(t *testing.T) { testDesc: "cluster not bootstrapped, should not reconcile", status: &v1beta1.PostgresClusterStatus{ PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, expectReconcile: false, expectRequeue: false, @@ -3691,7 +3729,8 @@ func TestReconcileScheduledBackups(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, expectReconcile: false, expectRequeue: false, @@ -3700,7 +3739,8 @@ func TestReconcileScheduledBackups(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, expectReconcile: false, expectRequeue: false, @@ -3710,7 +3750,8 @@ func TestReconcileScheduledBackups(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, expectReconcile: false, expectRequeue: false, @@ -3719,7 +3760,8 @@ func TestReconcileScheduledBackups(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}}, + Repos: []v1beta1.RepoStatus{{Name: "repo1", StanzaCreated: true}}, + }, }, expectReconcile: false, expectRequeue: false, @@ -3732,12 +3774,14 @@ func TestReconcileScheduledBackups(t *testing.T) { status: &v1beta1.PostgresClusterStatus{ Patroni: v1beta1.PatroniStatus{SystemIdentifier: "12345abcde"}, PGBackRest: &v1beta1.PGBackRestStatus{ - Repos: []v1beta1.RepoStatus{}}, + Repos: []v1beta1.RepoStatus{}, + }, }, expectReconcile: false, expectRequeue: false, expectedEventReason: "InvalidBackupRepo", - }} + }, + } for _, dedicated := range []bool{true, false} { for i, tc := range testCases { @@ -3751,7 +3795,6 @@ func TestReconcileScheduledBackups(t *testing.T) { } t.Run(tc.testDesc, func(t *testing.T) { - if tc.dedicatedOnly && !dedicated { t.Skip() } @@ -3763,7 +3806,8 @@ func TestReconcileScheduledBackups(t *testing.T) { postgresCluster.Status = *tc.status for condition, status := range tc.clusterConditions { meta.SetStatusCondition(&postgresCluster.Status.Conditions, metav1.Condition{ - Type: condition, Reason: "testing", Status: status}) + Type: condition, Reason: "testing", Status: status, + }) } assert.NilError(t, tClient.Status().Update(ctx, postgresCluster)) @@ -3777,7 +3821,8 @@ func TestReconcileScheduledBackups(t *testing.T) { naming.LabelCluster: clusterName, naming.LabelPGBackRestCronJob: "full", naming.LabelPGBackRestRepo: "repo1", - }}, + }, + }, }, { ObjectMeta: metav1.ObjectMeta{ Name: "existingcronjob-repo1-incr", @@ -3785,7 +3830,8 @@ func TestReconcileScheduledBackups(t *testing.T) { naming.LabelCluster: clusterName, naming.LabelPGBackRestCronJob: "incr", naming.LabelPGBackRestRepo: "repo1", - }}, + }, + }, }, { ObjectMeta: metav1.ObjectMeta{ Name: "existingcronjob-repo1-diff", @@ -3793,7 +3839,8 @@ func TestReconcileScheduledBackups(t *testing.T) { naming.LabelCluster: clusterName, naming.LabelPGBackRestCronJob: "diff", naming.LabelPGBackRestRepo: "repo1", - }}, + }, + }, }, } requeue = r.reconcileScheduledBackups(ctx, postgresCluster, sa, existingCronJobs) @@ -3988,7 +4035,8 @@ func TestBackupsEnabled(t *testing.T) { // create the 'observed' instances and set the leader instances := &observedInstances{ - forCluster: []*Instance{{Name: "instance1", + forCluster: []*Instance{{ + Name: "instance1", Pods: []*corev1.Pod{{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{naming.LabelRole: naming.RolePatroniLeader}, @@ -4039,7 +4087,8 @@ func TestBackupsEnabled(t *testing.T) { // create the 'observed' instances and set the leader instances := &observedInstances{ - forCluster: []*Instance{{Name: "instance1", + forCluster: []*Instance{{ + Name: "instance1", Pods: []*corev1.Pod{{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{naming.LabelRole: naming.RolePatroniLeader}, @@ -4075,7 +4124,8 @@ func TestBackupsEnabled(t *testing.T) { // create the 'observed' instances and set the leader instances := &observedInstances{ - forCluster: []*Instance{{Name: "instance1", + forCluster: []*Instance{{ + Name: "instance1", Pods: []*corev1.Pod{{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{naming.LabelRole: naming.RolePatroniLeader}, diff --git a/internal/controller/standalone_pgadmin/statefulset_test.go b/internal/controller/standalone_pgadmin/statefulset_test.go index 9eab30ab10..87c169ed1b 100644 --- a/internal/controller/standalone_pgadmin/statefulset_test.go +++ b/internal/controller/standalone_pgadmin/statefulset_test.go @@ -12,6 +12,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/percona/percona-postgresql-operator/v2/internal/initialize" @@ -35,6 +36,7 @@ func TestReconcilePGAdminStatefulSet(t *testing.T) { pgadmin := new(v1beta1.PGAdmin) pgadmin.Name = "test-standalone-pgadmin" pgadmin.Namespace = ns.Name + pgadmin.Spec.Image = ptr.To("some-image") assert.NilError(t, cc.Create(ctx, pgadmin)) t.Cleanup(func() { assert.Check(t, cc.Delete(ctx, pgadmin)) }) @@ -98,7 +100,6 @@ terminationGracePeriodSeconds: 30 }) t.Run("verify customized deployment", func(t *testing.T) { - custompgadmin := new(v1beta1.PGAdmin) // add pod level customizations @@ -136,9 +137,11 @@ terminationGracePeriodSeconds: 30 custompgadmin.Spec.PriorityClassName = initialize.String("testpriorityclass") } + custompgadmin.Spec.Image = ptr.To("someimage") // set an image pull secret custompgadmin.Spec.ImagePullSecrets = []corev1.LocalObjectReference{{ - Name: "myImagePullSecret"}} + Name: "myImagePullSecret", + }} assert.NilError(t, cc.Create(ctx, custompgadmin)) t.Cleanup(func() { assert.Check(t, cc.Delete(ctx, custompgadmin)) }) From 1f3b7adcae6b3429f42874de0754a572dc8cc3ab Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Thu, 8 Jan 2026 16:24:58 +0200 Subject: [PATCH 252/300] Skip `TestCheckForUpgradesScheduler` test --- internal/upgradecheck/http_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/upgradecheck/http_test.go b/internal/upgradecheck/http_test.go index 85762e7e40..fed01b7039 100644 --- a/internal/upgradecheck/http_test.go +++ b/internal/upgradecheck/http_test.go @@ -157,6 +157,7 @@ func TestCheckForUpgrades(t *testing.T) { // TODO(benjaminjb): Replace `fake` with envtest func TestCheckForUpgradesScheduler(t *testing.T) { + t.Skip("This test fails when run with 'go test ./...', but passes when run on its own.") // TODO: remove fakeClient := setupFakeClientWithPGOScheme(t, false) _, server := setupVersionServer(t, true) defer server.Close() From 9257546eb5d5ab7d1b4cc9b01f00e227a7198d94 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Mon, 12 Jan 2026 14:01:07 +0200 Subject: [PATCH 253/300] CLOUD-727 Update codeowners file --- .github/CODEOWNERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 107e2c58d7..5af2e49459 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ -* @hors @egegunes @pooknull @nmarukovich @gkech -/e2e-tests/ @jvpasinatto @eleo007 @valmiranogueira -Jenkinsfile @jvpasinatto @eleo007 @valmiranogueira +* @hors @egegunes @pooknull @nmarukovich @gkech @mayankshah1607 @oksana-grishchenko +/e2e-tests/ @jvpasinatto @eleo007 @valmiranogueira @bogdanjeler-ev @egegunes @pooknull @nmarukovich @gkech @mayankshah1607 @oksana-grishchenko +Jenkinsfile @jvpasinatto @eleo007 @valmiranogueira @bogdanjeler-ev From aee19223cccd699f353bbaed434d315de50e5cf7 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 19 Jan 2026 06:30:05 +0100 Subject: [PATCH 254/300] K8SPG-665: change exposeSuperusers example in cr.yaml (#1409) --- deploy/cr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/cr.yaml b/deploy/cr.yaml index bdd17d33fb..6fb3524ad6 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -319,7 +319,7 @@ spec: # envFrom: # - secretRef: # name: pgbouncer-env-secret -# exposeSuperusers: true +# exposeSuperusers: false # resources: # limits: # cpu: 200m From 68a0313d50a8dd70e8d22b0011cac35d11caa1aa Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 19 Jan 2026 11:30:08 +0100 Subject: [PATCH 255/300] K8SPG-740 fix error message --- percona/controller/pgcluster/backup.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 37d19b3557..0c1a7f105d 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -2,6 +2,8 @@ package pgcluster import ( "context" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "k8s.io/apimachinery/pkg/api/meta" "github.com/pkg/errors" batchv1 "k8s.io/api/batch/v1" @@ -27,6 +29,13 @@ func (r *PGClusterReconciler) reconcileBackups(ctx context.Context, cr *v2.Perco return errors.Wrap(err, "reconcile backup jobs") } + repoCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionRepoHostReady) + if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { + log.Info("pgBackRest repo host not ready, skipping backup cleanup") + return nil + + } + if err := r.cleanupOutdatedBackups(ctx, cr); err != nil { // If the user has invalid pgbackrest credentials, this could stop the reconcile. // We should just print an error message. From c6ee6312912f1b25f8b375035b5cd7d53374d61e Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 19 Jan 2026 11:37:05 +0100 Subject: [PATCH 256/300] fix import --- percona/controller/pgcluster/backup.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 0c1a7f105d..53b6028124 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -2,18 +2,18 @@ package pgcluster import ( "context" - "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" - "k8s.io/apimachinery/pkg/api/meta" "github.com/pkg/errors" batchv1 "k8s.io/api/batch/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" "github.com/percona/percona-postgresql-operator/v2/internal/logging" "github.com/percona/percona-postgresql-operator/v2/internal/naming" "github.com/percona/percona-postgresql-operator/v2/percona/controller" From 89439223cdf7ff095efd203af7bfe21b58397fdc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:02:09 +0200 Subject: [PATCH 257/300] CLOUD-727: Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#1406) Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.63.0 to 0.64.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.63.0...zpages/v0.64.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp dependency-version: 0.64.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8728ac2855..c2685664b8 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.33.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 go.opentelemetry.io/otel v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 diff --git a/go.sum b/go.sum index 82cdd3bc5a..2018a06f7a 100644 --- a/go.sum +++ b/go.sum @@ -249,8 +249,8 @@ go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= go.nhat.io/wait v0.1.0/go.mod h1:+ijMghc9/9zXi+HDcs49HNReprvXOZha2Q3jTOtqJrE= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ= go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= From 58c3a2c95fd6ff47950deeed6b891fab618bd09e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:04:45 +0200 Subject: [PATCH 258/300] CLOUD-727: Bump golang.org/x/crypto from 0.46.0 to 0.47.0 (#1404) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.46.0 to 0.47.0. - [Commits](https://github.com/golang/crypto/compare/v0.46.0...v0.47.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-version: 0.47.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index c2685664b8..bcc34ebce1 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.39.0 go.opentelemetry.io/otel/trace v1.39.0 go.uber.org/zap v1.27.1 - golang.org/x/crypto v0.46.0 + golang.org/x/crypto v0.47.0 google.golang.org/grpc v1.77.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.35.0 @@ -68,7 +68,7 @@ require ( go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.30.0 // indirect + golang.org/x/mod v0.31.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect @@ -122,14 +122,14 @@ require ( go.opentelemetry.io/otel/metric v1.39.0 // indirect go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.47.0 // indirect + golang.org/x/net v0.48.0 // indirect golang.org/x/oauth2 v0.32.0 // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.39.0 // indirect - golang.org/x/term v0.38.0 // indirect - golang.org/x/text v0.32.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.39.0 + golang.org/x/tools v0.40.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect diff --git a/go.sum b/go.sum index 2018a06f7a..5356e6e9da 100644 --- a/go.sum +++ b/go.sum @@ -281,16 +281,16 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= -golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -303,25 +303,25 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= From 9f7d7917b7dfb857ba5d8bcf1b7f452acf25f0d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:06:10 +0200 Subject: [PATCH 259/300] CLOUD-727: Bump go.nhat.io/grpcmock from 0.33.0 to 0.34.0 (#1405) Bumps [go.nhat.io/grpcmock](https://github.com/nhatthm/grpcmock) from 0.33.0 to 0.34.0. - [Release notes](https://github.com/nhatthm/grpcmock/releases) - [Commits](https://github.com/nhatthm/grpcmock/compare/v0.33.0...v0.34.0) --- updated-dependencies: - dependency-name: go.nhat.io/grpcmock dependency-version: 0.34.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 9 ++++----- go.sum | 34 ++++++++++------------------------ 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index bcc34ebce1..e03ce6ae6e 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 - go.nhat.io/grpcmock v0.33.0 + go.nhat.io/grpcmock v0.34.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 go.opentelemetry.io/otel v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 @@ -62,7 +62,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/google/btree v1.1.3 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/x448/float16 v0.8.4 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect @@ -78,7 +78,7 @@ require ( github.com/aws/aws-sdk-go v1.55.8 github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/bool64/shared v0.1.5 // indirect + github.com/bool64/shared v0.1.6 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect @@ -113,8 +113,7 @@ require ( github.com/spf13/afero v1.15.0 // indirect github.com/spf13/pflag v1.0.9 // indirect github.com/stretchr/testify v1.11.1 - github.com/swaggest/assertjson v1.9.0 // indirect - github.com/yudai/gojsondiff v1.0.0 // indirect + github.com/swaggest/assertjson v1.10.0 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect go.mongodb.org/mongo-driver v1.17.6 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect diff --git a/go.sum b/go.sum index 5356e6e9da..df4746d53f 100644 --- a/go.sum +++ b/go.sum @@ -10,10 +10,10 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bool64/dev v0.2.29 h1:x+syGyh+0eWtOzQ1ItvLzOGIWyNWnyjXpHIcpF2HvL4= -github.com/bool64/dev v0.2.29/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= -github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= -github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= +github.com/bool64/dev v0.2.43 h1:yQ7qiZVef6WtCl2vDYU0Y+qSq+0aBrQzY8KXkklk9cQ= +github.com/bool64/dev v0.2.43/go.mod h1:iJbh1y/HkunEPhgebWRNcs8wfGq7sjvJ6W5iabL8ACg= +github.com/bool64/shared v0.1.6 h1:1u1IfTU84pZU285Mf1kQC5wX/VzSRE5E/+4KgFRGQ6o= +github.com/bool64/shared v0.1.6/go.mod h1:AByMlOFBjavJDk8VdFBH/atMgv1q7qrKXD1XLAQTgZA= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -122,8 +122,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 h1:sGm2vDRFUrQJO/Veii4h4zG2vvqG6uWNkBHSTqXOZk0= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2/go.mod h1:wd1YpapPLivG6nQgbf7ZkG1hhSOXDhhn4MLTknx2aAc= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= @@ -153,10 +153,6 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= @@ -171,12 +167,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= -github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM= @@ -216,8 +208,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= -github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= +github.com/swaggest/assertjson v1.10.0 h1:OYIx29UbgqjwAekKbeIO8T0XbAMyViJ8qqrVj2GQY2M= +github.com/swaggest/assertjson v1.10.0/go.mod h1:31+ufMpzrCO/daIRZ4s1UZAA1R2q9EEUfJaoczgAty8= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -230,19 +222,15 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver v1.17.6 h1:87JUG1wZfWsr6rIz3ZmpH90rL5tea7O3IHuSwHUpsss= go.mongodb.org/mongo-driver v1.17.6/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.nhat.io/aferomock v0.8.0 h1:jESv25NuTpA/Wga+AOKqKI1lPKdYiBYvxpIUDJWyfPM= go.nhat.io/aferomock v0.8.0/go.mod h1:thJD/9Yeo+CcIW45u6rNU8WYc1yIWdqfOSpKcGtjAXw= -go.nhat.io/grpcmock v0.33.0 h1:R9lfxT36n4ytmSJadIVXucpsORoGVLyUiQh2yxtpWZU= -go.nhat.io/grpcmock v0.33.0/go.mod h1:f0z3MfHiMqnKLLkx+y8CiMB4xJTRWWSMKDM3Xvfl+jY= +go.nhat.io/grpcmock v0.34.0 h1:RXAU4nsXVR8+fVnKSS74puD2YLNCe89hToSuIS3Fw44= +go.nhat.io/grpcmock v0.34.0/go.mod h1:c5iA0AnWxRfxJhmLXn3T9FrFYDr13PE4NujEzumwF5E= go.nhat.io/matcher/v2 v2.0.0 h1:W+rbHi0hKuZHtOQH4U5g+KwyKyfVioIxrxjoGRcUETE= go.nhat.io/matcher/v2 v2.0.0/go.mod h1:cL5oYp0M9A4L8jEGqjmUfy+k7AXVDddoVt6aYIL1r5g= go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= @@ -346,8 +334,6 @@ gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnf gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= From 9dffe4766874a83cbecdb2b5da0f79ed805d8178 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:07:31 +0200 Subject: [PATCH 260/300] CLOUD-727: Bump golang.org/x/tools from 0.39.0 to 0.41.0 (#1399) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.39.0 to 0.41.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.39.0...v0.41.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-version: 0.41.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index e03ce6ae6e..11b5fc258c 100644 --- a/go.mod +++ b/go.mod @@ -68,7 +68,7 @@ require ( go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/mod v0.31.0 // indirect + golang.org/x/mod v0.32.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect @@ -121,14 +121,14 @@ require ( go.opentelemetry.io/otel/metric v1.39.0 // indirect go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.48.0 // indirect + golang.org/x/net v0.49.0 // indirect golang.org/x/oauth2 v0.32.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/term v0.39.0 // indirect golang.org/x/text v0.33.0 // indirect golang.org/x/time v0.9.0 // indirect - golang.org/x/tools v0.40.0 + golang.org/x/tools v0.41.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect diff --git a/go.sum b/go.sum index df4746d53f..efe8306ec1 100644 --- a/go.sum +++ b/go.sum @@ -272,13 +272,13 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= -golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -308,8 +308,8 @@ golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= -golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= From 94b3f1dcc8cd75cba03efffc17521ba5cc03b346 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:09:04 +0200 Subject: [PATCH 261/300] CLOUD-727: Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp (#1401) Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) from 1.38.0 to 1.39.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.38.0...v1.39.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp dependency-version: 1.39.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 11b5fc258c..bdd5535e23 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 go.opentelemetry.io/otel v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 go.opentelemetry.io/otel/sdk v1.39.0 go.opentelemetry.io/otel/trace v1.39.0 @@ -130,8 +130,8 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.41.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/protobuf v1.36.10 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index efe8306ec1..311ac98723 100644 --- a/go.sum +++ b/go.sum @@ -243,8 +243,8 @@ go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 h1:8UPA4IbVZxpsD76ihGOQiFml99GPAEZLohDXvqHdi6U= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0/go.mod h1:MZ1T/+51uIVKlRzGw1Fo46KEWThjlCBZKl2LzY5nv4g= go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= @@ -316,10 +316,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= -google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= From 63566de0b0967045050aca92ff9be5e9074cc587 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 21:11:08 +0200 Subject: [PATCH 262/300] CLOUD-727: Bump github.com/onsi/ginkgo/v2 from 2.27.2 to 2.27.5 (#1398) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.27.2 to 2.27.5. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.27.2...v2.27.5) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-version: 2.27.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bdd5535e23..900090711b 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.8.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 - github.com/onsi/ginkgo/v2 v2.27.2 + github.com/onsi/ginkgo/v2 v2.27.5 github.com/onsi/gomega v1.38.3 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 311ac98723..e17a06673f 100644 --- a/go.sum +++ b/go.sum @@ -169,8 +169,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= -github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE= +github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM= github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= From e3561efc32eede6ba8ec60792e082aa2d6047df1 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Mon, 19 Jan 2026 21:11:42 +0200 Subject: [PATCH 263/300] K8SPG-901: fix panic (#1391) https://perconadev.atlassian.net/browse/K8SPG-901 Co-authored-by: Viacheslav Sarzhan --- pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 77d4789b78..613ae8fe15 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -1111,7 +1111,7 @@ func (cr *PerconaPGCluster) EnvFromSecrets() []string { } } - if len(cr.Spec.Proxy.PGBouncer.EnvFrom) > 0 { + if cr.Spec.Proxy != nil && cr.Spec.Proxy.PGBouncer != nil && len(cr.Spec.Proxy.PGBouncer.EnvFrom) > 0 { for _, envFrom := range cr.Spec.Proxy.PGBouncer.EnvFrom { if envFrom.SecretRef == nil { continue From 5b9e2d2a2df52d474abc78755c3449118eb012aa Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 20 Jan 2026 12:36:57 +0100 Subject: [PATCH 264/300] fix PR comments --- percona/controller/pgcluster/backup.go | 1 - 1 file changed, 1 deletion(-) diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 53b6028124..71eb41b580 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -33,7 +33,6 @@ func (r *PGClusterReconciler) reconcileBackups(ctx context.Context, cr *v2.Perco if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { log.Info("pgBackRest repo host not ready, skipping backup cleanup") return nil - } if err := r.cleanupOutdatedBackups(ctx, cr); err != nil { From b5165f5851626dcd95490e3525520c686fdad98e Mon Sep 17 00:00:00 2001 From: Mayank Shah Date: Wed, 21 Jan 2026 10:04:28 +0530 Subject: [PATCH 265/300] K8SPG-933: standby cannot be created (#1410) Signed-off-by: Mayank Shah --- percona/controller/pgcluster/controller.go | 13 ++- .../controller/pgcluster/patroniversion.go | 93 +++++++++++-------- .../pgcluster/patroniversion_test.go | 2 +- .../v1beta1/postgrescluster_types.go | 4 + 4 files changed, 69 insertions(+), 43 deletions(-) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index a7685ecde8..2af967cc2b 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -265,13 +265,13 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "ensure finalizers") } - if err := r.reconcilePatroniVersion(ctx, cr); err != nil { + if err := r.reconcilePatroniVersionCheckPod(ctx, cr); err != nil { if errors.Is(err, errPatroniVersionCheckWait) { return reconcile.Result{ RequeueAfter: 5 * time.Second, }, nil } - return reconcile.Result{}, errors.Wrap(err, "check patroni version") + return reconcile.Result{}, errors.Wrap(err, "check patroni version pod") } if err := r.reconcileTLS(ctx, cr); err != nil { @@ -356,6 +356,15 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return ctrl.Result{}, errors.Wrap(err, "update status") } + if err := r.reconcilePatroniVersionFromCluster(ctx, cr); err != nil { + if errors.Is(err, errPatroniVersionCheckWait) { + return reconcile.Result{ + RequeueAfter: 5 * time.Second, + }, nil + } + return reconcile.Result{}, errors.Wrap(err, "check patroni version from instance pods") + } + return ctrl.Result{}, nil } diff --git a/percona/controller/pgcluster/patroniversion.go b/percona/controller/pgcluster/patroniversion.go index bb305cb997..50bf0addd6 100644 --- a/percona/controller/pgcluster/patroniversion.go +++ b/percona/controller/pgcluster/patroniversion.go @@ -27,59 +27,72 @@ import ( v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) -var errPatroniVersionCheckWait = errors.New("waiting for pod to initialize") +func (r *PGClusterReconciler) reconcilePatroniVersionFromCluster(ctx context.Context, cr *v2.PerconaPGCluster) error { + if cr.CompareVersion("2.8.0") < 0 { + return nil + } -func (r *PGClusterReconciler) reconcilePatroniVersion(ctx context.Context, cr *v2.PerconaPGCluster) error { - if cr.Annotations == nil { - cr.Annotations = make(map[string]string) + pods, err := r.getInstancePods(ctx, cr) + if err != nil { + return errors.Wrap(err, "failed to get instance pods") } - if cr.CompareVersion("2.7.0") <= 0 { - if patroniVersion, ok := cr.Annotations[pNaming.AnnotationCustomPatroniVersion]; ok { - err := r.handleCustomPatroniVersionAnnotation(ctx, cr, patroniVersion) - if err != nil { - return errors.Wrap(err, "handle patroni annotation") - } - return nil - } + if len(pods.Items) == 0 || pods.Items[0].Status.Phase != corev1.PodRunning { + return errPatroniVersionCheckWait } - // Starting from version 2.8.0, the patroni version check pod should not be executed. - if cr.CompareVersion("2.8.0") >= 0 { - pods, err := r.getInstancePods(ctx, cr) - if err != nil { - return errors.Wrap(err, "failed to get instance pods") - } - if len(pods.Items) == 0 { - return errors.Wrap(err, "instance pods not available") - } + p := pods.Items[0] + imageID := getImageIDFromPod(&p, naming.ContainerDatabase) + pgVersion := cr.Spec.PostgresVersion - p := pods.Items[0] + // If patroni version is set, and neither imageID nor PG version have changed, + // we don't need to check the patroni version again. + if cr.Status.Patroni.Version != "" && + cr.Status.Postgres.ImageID == imageID && + cr.Status.Postgres.Version == pgVersion { + return nil + } - if p.Status.Phase != corev1.PodRunning { - return errPatroniVersionCheckWait - } + patroniVersion, err := r.getPatroniVersion(ctx, &p, naming.ContainerDatabase) + if err != nil { + return errors.Wrap(err, "failed to get patroni version") + } - patroniVersion, err := r.getPatroniVersion(ctx, &p, naming.ContainerDatabase) - if err != nil { - return errors.Wrap(err, "failed to get patroni version") - } + orig := cr.DeepCopy() - orig := cr.DeepCopy() + cr.Status.Patroni.Version = patroniVersion + cr.Status.PatroniVersion = patroniVersion + cr.Status.Postgres.Version = pgVersion + cr.Status.Postgres.ImageID = imageID - cr.Status.Patroni.Version = patroniVersion - cr.Status.PatroniVersion = patroniVersion - cr.Status.Postgres.Version = cr.Spec.PostgresVersion - cr.Status.Postgres.ImageID = getImageIDFromPod(&p, naming.ContainerDatabase) + if err := r.Client.Status().Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "failed to patch patroni version") + } - if err := r.Client.Status().Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { - return errors.Wrap(err, "failed to patch patroni version") - } + err = r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) + if err != nil { + return errors.Wrap(err, "failed to patch patroni version annotation") + } + + return nil +} - err = r.patchPatroniVersionAnnotation(ctx, cr, patroniVersion) +var errPatroniVersionCheckWait = errors.New("waiting for pod to initialize") + +func (r *PGClusterReconciler) reconcilePatroniVersionCheckPod(ctx context.Context, cr *v2.PerconaPGCluster) error { + // Starting from version 2.8.0, the patroni version check pod should not be executed. + if cr.CompareVersion("2.8.0") >= 0 { + return nil + } + + if cr.Annotations == nil { + cr.Annotations = make(map[string]string) + } + + if patroniVersion, ok := cr.Annotations[pNaming.AnnotationCustomPatroniVersion]; ok { + err := r.handleCustomPatroniVersionAnnotation(ctx, cr, patroniVersion) if err != nil { - return errors.Wrap(err, "failed to patch patroni version annotation") + return errors.Wrap(err, "handle patroni annotation") } - return nil } diff --git a/percona/controller/pgcluster/patroniversion_test.go b/percona/controller/pgcluster/patroniversion_test.go index bcd876d3bb..e83363ffe7 100644 --- a/percona/controller/pgcluster/patroniversion_test.go +++ b/percona/controller/pgcluster/patroniversion_test.go @@ -114,7 +114,7 @@ var _ = Describe("patroni version check", Ordered, func() { It("should create patroni version check pod and return errPatroniVersionCheckWait", func() { reconcilerInstance := reconciler(cr2) - err := reconcilerInstance.reconcilePatroniVersion(ctx, cr2) + err := reconcilerInstance.reconcilePatroniVersionCheckPod(ctx, cr2) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("waiting for pod to initialize")) }) diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 7ab7fa7894..5bb7e58f4f 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -791,6 +791,10 @@ func (cr *PostgresCluster) CompareVersion(ver string) int { func (cr *PostgresCluster) IsPatroniVer4() (bool, error) { patroniVerStr, ok := cr.Annotations[pNaming.ToCrunchyAnnotation(pNaming.AnnotationPatroniVersion)] if !ok { + // Assume Patroni v4 for CR versions greater than 2.7.0 + if cr.CompareVersion("2.7.0") >= 0 { + return true, nil + } return false, errors.New("patroni version annotation was not found") } patroniVer, err := gover.NewVersion(patroniVerStr) From f7f78adc9cc78278af97247b4d1d8b0882817d24 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 2 Feb 2026 13:54:02 +0100 Subject: [PATCH 266/300] K8SPG-740 add test for huge pages --- e2e-tests/functions | 444 ++++++++++++++++++ e2e-tests/tests/huge-pages/00-assert.yaml | 24 + .../tests/huge-pages/00-deploy-operator.yaml | 13 + e2e-tests/tests/huge-pages/01-assert.yaml | 174 +++++++ .../tests/huge-pages/01-create-cluster.yaml | 18 + .../tests/huge-pages/02-verify-hugepages.yaml | 29 ++ .../99-remove-cluster-gracefully.yaml | 21 + 7 files changed, 723 insertions(+) create mode 100644 e2e-tests/tests/huge-pages/00-assert.yaml create mode 100644 e2e-tests/tests/huge-pages/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/huge-pages/01-assert.yaml create mode 100644 e2e-tests/tests/huge-pages/01-create-cluster.yaml create mode 100644 e2e-tests/tests/huge-pages/02-verify-hugepages.yaml create mode 100644 e2e-tests/tests/huge-pages/99-remove-cluster-gracefully.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index 6b2a23167e..051cbb5b64 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -354,6 +354,17 @@ get_cr() { .spec.extensions.storage = {"type": "s3", "bucket": "operator-testing", "region": "us-east-1", "endpoint": "http://minio-service:9000", "forcePathStyle": true, "disableSSL": true, "secret": {"name": "minio-secret"}} ' $TEMP_DIR/cr.yaml ;; + "huge-pages") + if [ "${platform}" == "aks" ] ; then + yq eval -i ' + .spec.instances |= ( + .[] |= ( + .affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms = + [{"matchExpressions":[{"key":"hugepages","operator":"In","values":["enabled"]}]}] + ) + ) + ' "$TEMP_DIR/cr.yaml" + fi esac cat $TEMP_DIR/cr.yaml } @@ -1256,4 +1267,437 @@ check_envs_for_component() { else echo "All environment checks passed for component '$component'" fi +} + +detect_k8s_platform() { + local platform="" + + if kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "gce://"; then + platform="gke" + + elif oc get projects >/dev/null 2>&1; then + platform="openshift" + + elif kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "aws://"; then + platform="eks" + + elif kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "azure://"; then + platform="aks" + + else + platform="unknown" + fi + + echo "${platform}" +} + +enable_hugepages() { + local platform=$1 + local hugepage_count=${2:-1024} + + echo "Detected platform: ${platform}" + + case ${platform} in + gke) + enable_hugepages_gke "${hugepage_count}" + ;; + openshift) + enable_hugepages_openshift "${hugepage_count}" + ;; + eks) + enable_hugepages_eks "${hugepage_count}" + ;; + aks) + enable_hugepages_aks "${hugepage_count}" + ;; + *) + echo "Unknown platform, cannot configure hugepages" + return 1 + ;; + esac +} + +enable_hugepages_gke() { + local hugepage_count=$1 + + echo "Configuring hugepages on GKE" + + # Get node info + local node_name=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') + echo "Sample node: ${node_name}" + + local provider_id=$(kubectl get node ${node_name} -o jsonpath='{.spec.providerID}') + echo "Provider ID: ${provider_id}" + + # Parse providerID + local gke_project="" + local gke_zone="" + local instance_name="" + + if [[ "${provider_id}" =~ ^gce://([^/]+)/([^/]+)/(.+)$ ]]; then + gke_project="${BASH_REMATCH[1]}" + gke_zone="${BASH_REMATCH[2]}" + instance_name="${BASH_REMATCH[3]}" + else + echo "Could not parse providerID: ${provider_id}" + return 1 + fi + + local gke_cluster="" + if [[ "${instance_name}" =~ ^gke-([^-]+-[^-]+)-.*$ ]]; then + gke_cluster="${BASH_REMATCH[1]}" + elif [[ "${instance_name}" =~ ^gke-([^-]+)-.*$ ]]; then + gke_cluster="${BASH_REMATCH[1]}" + else + echo "Could not extract cluster name from instance: ${instance_name}" + return 1 + fi + + local gke_location="${gke_zone%-*}" + + if [ -z "${gke_cluster}" ] || [ -z "${gke_location}" ] || [ -z "${gke_project}" ]; then + echo "Could not determine GKE cluster information" + echo "Cluster: ${gke_cluster}" + echo "Location: ${gke_location}" + echo "Zone: ${gke_zone}" + echo "Project: ${gke_project}" + return 1 + fi + + local node_pool=${GKE_NODE_POOL:-default-pool} + + echo "Project: ${gke_project}" + echo "Zone: ${gke_zone}" + echo "Region: ${gke_location}" + echo "Cluster: ${gke_cluster}" + echo "Node pool: ${node_pool}" + echo "Hugepages (2Mi): ${hugepage_count}" + + cat > /tmp/node-pool-config.yaml </dev/null; then + + echo "Node pool updated (regional cluster)" + + elif gcloud container node-pools update ${node_pool} \ + --cluster ${gke_cluster} \ + --zone ${gke_zone} \ + --project ${gke_project} \ + --system-config-from-file=/tmp/node-pool-config.yaml 2>/dev/null; then + + echo "Node pool updated (zonal cluster)" + else + echo "Failed to update node pool" + rm -f /tmp/node-pool-config.yaml + return 1 + fi + + echo "Waiting for nodes to restart..." + sleep 60 + kubectl wait --for=condition=Ready nodes --all --timeout=300s + + rm -f /tmp/node-pool-config.yaml + echo "Hugepages configured on GKE" + return 0 +} + +enable_hugepages_eks() { + local hugepage_count=$1 + + echo "Configuring hugepages on EKS" + + if verify_hugepages_on_nodes; then + echo "Hugepages already configured" + return 0 + fi +} + +enable_hugepages_aks() { + local hugepage_count="${1:-2048}" + local nodepool_name="${AKS_HUGEPAGES_NODEPOOL:-hp2m}" + local vm_size="${AKS_HUGEPAGES_VM_SIZE:-Standard_D4_v2}" + local node_count="${AKS_HUGEPAGES_NODE_COUNT:-1}" + + echo "Checking hugepages on AKS..." + + if verify_hugepages_on_nodes 2>/dev/null; then + echo "Hugepages already configured" + return 0 + fi + + local cluster_name + node_rg="$(kubectl get nodes -o jsonpath='{.items[0].metadata.labels.kubernetes\.azure\.com/cluster}' 2>/dev/null || true)" + [[ -n "$node_rg" ]] || return 1 + + + aks_id="$(az aks list --subscription "${AZURE_SUBSCRIPTION:-eng-cloud-dev}" \ + --query "[?nodeResourceGroup=='$node_rg'] | [0].id" \ + -o tsv 2>/dev/null || true)" + [[ -n "$aks_id" ]] || return 1 + + cluster_name="$(echo "$aks_id" | sed -E 's|.*/managedClusters/([^/]+)$|\1|I')" + [[ -n "$cluster_name" ]] || return 1 + + if [[ -z "${cluster_name}" ]]; then + echo "AKS: can't detect cluster name from node labels." + echo "Skipping hugepages test." + return 1 + fi + + echo "AKS cluster detected: ${cluster_name}" + + if ! az aks nodepool show -g percona-operators --cluster-name "${cluster_name}" -n "${nodepool_name}" >/dev/null 2>&1; then + echo "Creating nodepool '${nodepool_name}' (${vm_size}, count=${node_count}) with label hugepages=enabled..." + az aks nodepool add \ + --subscription "${AZURE_SUBSCRIPTION:-eng-cloud-dev}" \ + -g "${AKS_RG:-percona-operators}" \ + --cluster-name "${cluster_name}" \ + -n "${nodepool_name}" \ + --node-count "${node_count}" \ + --node-vm-size "${vm_size}" \ + --labels hugepages=enabled \ + --mode User + else + echo "Nodepool '${nodepool_name}' already exists." + fi + + echo "Waiting for hugepages node(s) to be Ready..." + kubectl wait node -l hugepages=enabled --for=condition=Ready --timeout=15m || { + echo "AKS: hugepages node(s) not ready in time. Skipping test." + return 1 + } + + echo "Applying DaemonSet to allocate hugepages on hugepages=enabled nodes (HP_2M=${hugepage_count})..." + cat < /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages + mkdir -p /host/etc/sysctl.d + echo "vm.nr_hugepages=\${HP_2M}" > /host/etc/sysctl.d/60-hugepages.conf + chroot /host /bin/sh -c "sysctl -w vm.nr_hugepages=\${HP_2M} || true; systemctl restart kubelet || true" + echo "Done. Sleeping..." + sleep infinity + volumeMounts: + - name: host-root + mountPath: /host + - name: sys + mountPath: /sys + volumes: + - name: host-root + hostPath: + path: / + - name: sys + hostPath: + path: /sys +EOF + + kubectl -n kube-system rollout status ds/hugepages-2mi-enable --timeout=10m || { + echo "AKS: DaemonSet rollout did not complete. Skipping test." + return 1 + } + + echo "Re-checking hugepages on nodes..." + if verify_hugepages_on_nodes 2>/dev/null; then + echo "Hugepages configured successfully" + return 0 + fi + + echo "AKS: Hugepages still not visible after configuration." + echo "Skipping hugepages test." + return 1 +} + +enable_hugepages_openshift() { + local hugepage_count=$1 + + echo "Configuring hugepages on OpenShift" + + if verify_hugepages_on_nodes; then + echo "Hugepages already configured" + return 0 + fi + + echo "Creating MachineConfig..." + + cat </dev/null || { + echo "Update taking longer than expected" + return 1 + } + + echo "Worker pool updated" + + sleep 10 + verify_hugepages_on_nodes +} + +verify_hugepages_on_nodes() { + echo "Verifying hugepages on nodes" + + # Get first worker node, fallback to first non-master, fallback to any node + local node_name=$( + kubectl get nodes -l node-role.kubernetes.io/worker -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || \ + kubectl get nodes -l '!node-role.kubernetes.io/master,!node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || \ + kubectl get nodes -o jsonpath='{.items[0].metadata.name}' + ) + + if [ -z "${node_name}" ]; then + echo "No nodes found" + return 1 + fi + + echo "Checking node: ${node_name}" + + local hugepages_capacity=$(kubectl get node ${node_name} \ + -o jsonpath='{.status.capacity.hugepages-2Mi}') + + if [ -n "${hugepages_capacity}" ] && [ "${hugepages_capacity}" != "0" ]; then + echo "Node has hugepages capacity: ${hugepages_capacity}" + return 0 + else + echo "No hugepages capacity found on node ${node_name}" + return 1 + fi +} + +verify_hugepages_in_pod() { + local pod_name=$1 + local namespace=$2 + local container=${3:-postgres} + + echo "Verifying hugepages in pod ${pod_name}" + + # Check /proc/meminfo + local hugepages_total=$(kubectl exec ${pod_name} -n ${namespace} -c ${container} -- \ + grep HugePages_Total /proc/meminfo | awk '{print $2}') + + local hugepages_free=$(kubectl exec ${pod_name} -n ${namespace} -c ${container} -- \ + grep HugePages_Free /proc/meminfo | awk '{print $2}') + + echo "HugePages_Total: ${hugepages_total}" + echo "HugePages_Free: ${hugepages_free}" + + if [ "${hugepages_total}" -gt 0 ]; then + echo "Hugepages are available in pod" + return 0 + else + echo "No hugepages in pod" + return 1 + fi +} + +verify_postgresql_hugepages_setting() { + local cluster_name=$1 + local expected_value=${2:-try} + + echo "Verifying PostgreSQL huge_pages setting..." + + local huge_pages=$(run_psql_local \ + "SHOW huge_pages;" \ + "postgres:$(get_psql_user_pass ${cluster_name}-pguser-postgres)@$(get_psql_user_host ${cluster_name}-pguser-postgres)") + + echo "huge_pages: ${huge_pages}" + + if [[ "${huge_pages}" == *"${expected_value}"* ]]; then + echo "PostgreSQL huge_pages is set to '${expected_value}'" + return 0 + else + echo "PostgreSQL huge_pages not set to '${expected_value}' (value: ${huge_pages})" + return 1 + fi +} + +verify_hugepages_usage() { + local pod_name=$1 + local namespace=$2 + local container=${3:-database} + + echo "Checking hugepages usage..." + + kubectl -n ${namespace} exec ${pod_name} -c ${container} -- \ + grep HugePages /proc/meminfo + + local hugepages_total=$(kubectl -n ${namespace} exec ${pod_name} -c ${container} -- \ + grep HugePages_Total /proc/meminfo | awk '{print $2}') + + local hugepages_free=$(kubectl -n ${namespace} exec ${pod_name} -c ${container} -- \ + grep HugePages_Free /proc/meminfo | awk '{print $2}') + + local hugepages_used=$((hugepages_total - hugepages_free)) + + echo "" + echo "HugePages usage:" + echo " Total: ${hugepages_total}" + echo " Used: ${hugepages_used}" + + if [ "${hugepages_used}" -gt 0 ]; then + echo "PostgreSQL is using hugepages" + return 0 + else + echo "Hugepages available but NOT being used by PostgreSQL" + return 1 + fi } \ No newline at end of file diff --git a/e2e-tests/tests/huge-pages/00-assert.yaml b/e2e-tests/tests/huge-pages/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/huge-pages/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/huge-pages/00-deploy-operator.yaml b/e2e-tests/tests/huge-pages/00-deploy-operator.yaml new file mode 100644 index 0000000000..c35cee0284 --- /dev/null +++ b/e2e-tests/tests/huge-pages/00-deploy-operator.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client \ No newline at end of file diff --git a/e2e-tests/tests/huge-pages/01-assert.yaml b/e2e-tests/tests/huge-pages/01-assert.yaml new file mode 100644 index 0000000000..996776f013 --- /dev/null +++ b/e2e-tests/tests/huge-pages/01-assert.yaml @@ -0,0 +1,174 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: huge-pages-repo-host + labels: + postgres-operator.crunchydata.com/cluster: huge-pages + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: huge-pages + controller: true + blockOwnerDeletion: true +spec: + serviceName: huge-pages-pods + template: + spec: + containers: + - command: + - pgbackrest + - server + name: pgbackrest + - command: + - bash + - -ceu + - -- + - |- + monitor() { + exec {fd}<> <(:||:) + until read -r -t 5 -u "${fd}"; do + if + [[ "${filename}" -nt "/proc/self/fd/${fd}" ]] && + pkill -HUP --exact --parent=0 pgbackrest + then + exec {fd}>&- && exec {fd}<> <(:||:) + stat --dereference --format='Loaded configuration dated %y' "${filename}" + elif + { [[ "${directory}" -nt "/proc/self/fd/${fd}" ]] || + [[ "${authority}" -nt "/proc/self/fd/${fd}" ]] + } && + pkill -HUP --exact --parent=0 pgbackrest + then + exec {fd}>&- && exec {fd}<> <(:||:) + stat --format='Loaded certificates dated %y' "${directory}" + fi + done + }; export directory="$1" authority="$2" filename="$3"; export -f monitor; exec -a "$0" bash -ceu monitor + - pgbackrest-config + - /etc/pgbackrest/server + - /etc/pgbackrest/conf.d/~postgres-operator/tls-ca.crt + - /etc/pgbackrest/conf.d/~postgres-operator_server.conf + name: pgbackrest-config +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: huge-pages + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: huge-pages + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: huge-pages-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: huge-pages + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: huge-pages + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + updatedReplicas: 1 + readyReplicas: 1 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: huge-pages + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: huge-pages + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: huge-pages + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 + observedGeneration: 1 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: huge-pages +status: + pgbouncer: + ready: 1 + size: 1 + postgres: + instances: + - name: instance1 + ready: 1 + size: 1 + ready: 1 + size: 1 + state: ready diff --git a/e2e-tests/tests/huge-pages/01-create-cluster.yaml b/e2e-tests/tests/huge-pages/01-create-cluster.yaml new file mode 100644 index 0000000000..c60904ccd5 --- /dev/null +++ b/e2e-tests/tests/huge-pages/01-create-cluster.yaml @@ -0,0 +1,18 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + platform=$(detect_k8s_platform) + enable_hugepages $platform + get_cr \ + | yq '.spec.instances[0].resources.limits.hugepages-2Mi = "2Gi"' \ + | yq '.spec.proxy.pgBouncer.replicas=1' \ + | yq '.spec.instances[].replicas=1' \ + | yq '.spec.instances[0].resources.limits.memory = "4Gi"' \ + | yq '.spec.patroni.dynamicConfiguration.postgresql.parameters.shared_buffers = "1GB"' \ + | kubectl -n "${NAMESPACE}" apply -f - \ No newline at end of file diff --git a/e2e-tests/tests/huge-pages/02-verify-hugepages.yaml b/e2e-tests/tests/huge-pages/02-verify-hugepages.yaml new file mode 100644 index 0000000000..231f81c126 --- /dev/null +++ b/e2e-tests/tests/huge-pages/02-verify-hugepages.yaml @@ -0,0 +1,29 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 120 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + PRIMARY=$(get_pod_by_role huge-pages primary name) + + # Verify hugepages available in pod + verify_hugepages_in_pod "${PRIMARY}" "${NAMESPACE}" "database" + + # Verify PostgreSQL setting + verify_postgresql_hugepages_setting "huge-pages" "try" + + echo "Running workload..." + run_psql_local \ + "DROP TABLE IF EXISTS test_hp; CREATE TABLE test_hp AS SELECT generate_series(1, 1000000) AS id; SELECT sum(id) FROM test_hp;" \ + "postgres:$(get_psql_user_pass huge-pages-pguser-postgres)@$(get_psql_user_host huge-pages-pguser-postgres)" + + sleep 5 + + # Verify usage + verify_hugepages_usage "${PRIMARY}" "${NAMESPACE}" "database" + + echo "Hugepages verification passed" \ No newline at end of file diff --git a/e2e-tests/tests/huge-pages/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/huge-pages/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..eed80092e7 --- /dev/null +++ b/e2e-tests/tests/huge-pages/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: huge-pages +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: huge-pages +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 From e147f2277e275e005839a95f03e23f662c363df3 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 2 Feb 2026 16:44:19 +0100 Subject: [PATCH 267/300] fix PR comments --- percona/controller/pgcluster/backup.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 71eb41b580..ae3402125c 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -29,12 +29,6 @@ func (r *PGClusterReconciler) reconcileBackups(ctx context.Context, cr *v2.Perco return errors.Wrap(err, "reconcile backup jobs") } - repoCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionRepoHostReady) - if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { - log.Info("pgBackRest repo host not ready, skipping backup cleanup") - return nil - } - if err := r.cleanupOutdatedBackups(ctx, cr); err != nil { // If the user has invalid pgbackrest credentials, this could stop the reconcile. // We should just print an error message. @@ -55,6 +49,12 @@ func (r *PGClusterReconciler) cleanupOutdatedBackups(ctx context.Context, cr *v2 return nil } + repoCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionRepoHostReady) + if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { + log.Info("pgBackRest repo host not ready, skipping backup cleanup") + return nil + } + for _, repo := range cr.Spec.Backups.PGBackRest.Repos { var info pgbackrest.InfoOutput From 1906cadf78b03e371eeab79dc98782dba3f312b6 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 3 Feb 2026 11:13:36 +0100 Subject: [PATCH 268/300] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- e2e-tests/functions | 364 ++++++++++++++++++++++---------------------- 1 file changed, 182 insertions(+), 182 deletions(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 051cbb5b64..50e4b3d202 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -354,9 +354,9 @@ get_cr() { .spec.extensions.storage = {"type": "s3", "bucket": "operator-testing", "region": "us-east-1", "endpoint": "http://minio-service:9000", "forcePathStyle": true, "disableSSL": true, "secret": {"name": "minio-secret"}} ' $TEMP_DIR/cr.yaml ;; - "huge-pages") - if [ "${platform}" == "aks" ] ; then - yq eval -i ' + "huge-pages") + if [ "${platform}" == "aks" ]; then + yq eval -i ' .spec.instances |= ( .[] |= ( .affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms = @@ -364,7 +364,8 @@ get_cr() { ) ) ' "$TEMP_DIR/cr.yaml" - fi + fi + ;; esac cat $TEMP_DIR/cr.yaml } @@ -1270,215 +1271,214 @@ check_envs_for_component() { } detect_k8s_platform() { - local platform="" + local platform="" - if kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "gce://"; then - platform="gke" + if kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "gce://"; then + platform="gke" - elif oc get projects >/dev/null 2>&1; then - platform="openshift" + elif oc get projects >/dev/null 2>&1; then + platform="openshift" - elif kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "aws://"; then - platform="eks" + elif kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "aws://"; then + platform="eks" - elif kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "azure://"; then - platform="aks" + elif kubectl get nodes -o json | jq -r '.items[0].spec.providerID' | grep -q "azure://"; then + platform="aks" - else - platform="unknown" - fi + else + platform="unknown" + fi - echo "${platform}" + echo "${platform}" } enable_hugepages() { - local platform=$1 - local hugepage_count=${2:-1024} - - echo "Detected platform: ${platform}" - - case ${platform} in - gke) - enable_hugepages_gke "${hugepage_count}" - ;; - openshift) - enable_hugepages_openshift "${hugepage_count}" - ;; - eks) - enable_hugepages_eks "${hugepage_count}" - ;; - aks) - enable_hugepages_aks "${hugepage_count}" - ;; - *) - echo "Unknown platform, cannot configure hugepages" - return 1 - ;; - esac + local platform=$1 + local hugepage_count=${2:-1024} + + echo "Detected platform: ${platform}" + + case ${platform} in + gke) + enable_hugepages_gke "${hugepage_count}" + ;; + openshift) + enable_hugepages_openshift "${hugepage_count}" + ;; + eks) + enable_hugepages_eks "${hugepage_count}" + ;; + aks) + enable_hugepages_aks "${hugepage_count}" + ;; + *) + echo "Unknown platform, cannot configure hugepages" + return 1 + ;; + esac } enable_hugepages_gke() { - local hugepage_count=$1 + local hugepage_count=$1 - echo "Configuring hugepages on GKE" + echo "Configuring hugepages on GKE" - # Get node info - local node_name=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') - echo "Sample node: ${node_name}" + # Get node info + local node_name=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') + echo "Sample node: ${node_name}" - local provider_id=$(kubectl get node ${node_name} -o jsonpath='{.spec.providerID}') - echo "Provider ID: ${provider_id}" + local provider_id=$(kubectl get node ${node_name} -o jsonpath='{.spec.providerID}') + echo "Provider ID: ${provider_id}" - # Parse providerID - local gke_project="" - local gke_zone="" - local instance_name="" + # Parse providerID + local gke_project="" + local gke_zone="" + local instance_name="" - if [[ "${provider_id}" =~ ^gce://([^/]+)/([^/]+)/(.+)$ ]]; then - gke_project="${BASH_REMATCH[1]}" - gke_zone="${BASH_REMATCH[2]}" - instance_name="${BASH_REMATCH[3]}" - else - echo "Could not parse providerID: ${provider_id}" - return 1 - fi + if [[ ${provider_id} =~ ^gce://([^/]+)/([^/]+)/(.+)$ ]]; then + gke_project="${BASH_REMATCH[1]}" + gke_zone="${BASH_REMATCH[2]}" + instance_name="${BASH_REMATCH[3]}" + else + echo "Could not parse providerID: ${provider_id}" + return 1 + fi - local gke_cluster="" - if [[ "${instance_name}" =~ ^gke-([^-]+-[^-]+)-.*$ ]]; then - gke_cluster="${BASH_REMATCH[1]}" - elif [[ "${instance_name}" =~ ^gke-([^-]+)-.*$ ]]; then - gke_cluster="${BASH_REMATCH[1]}" - else - echo "Could not extract cluster name from instance: ${instance_name}" - return 1 - fi + local gke_cluster="" + if [[ ${instance_name} =~ ^gke-([^-]+-[^-]+)-.*$ ]]; then + gke_cluster="${BASH_REMATCH[1]}" + elif [[ ${instance_name} =~ ^gke-([^-]+)-.*$ ]]; then + gke_cluster="${BASH_REMATCH[1]}" + else + echo "Could not extract cluster name from instance: ${instance_name}" + return 1 + fi - local gke_location="${gke_zone%-*}" + local gke_location="${gke_zone%-*}" - if [ -z "${gke_cluster}" ] || [ -z "${gke_location}" ] || [ -z "${gke_project}" ]; then - echo "Could not determine GKE cluster information" - echo "Cluster: ${gke_cluster}" - echo "Location: ${gke_location}" - echo "Zone: ${gke_zone}" - echo "Project: ${gke_project}" - return 1 - fi + if [ -z "${gke_cluster}" ] || [ -z "${gke_location}" ] || [ -z "${gke_project}" ]; then + echo "Could not determine GKE cluster information" + echo "Cluster: ${gke_cluster}" + echo "Location: ${gke_location}" + echo "Zone: ${gke_zone}" + echo "Project: ${gke_project}" + return 1 + fi - local node_pool=${GKE_NODE_POOL:-default-pool} + local node_pool=${GKE_NODE_POOL:-default-pool} - echo "Project: ${gke_project}" - echo "Zone: ${gke_zone}" - echo "Region: ${gke_location}" - echo "Cluster: ${gke_cluster}" - echo "Node pool: ${node_pool}" - echo "Hugepages (2Mi): ${hugepage_count}" + echo "Project: ${gke_project}" + echo "Zone: ${gke_zone}" + echo "Region: ${gke_location}" + echo "Cluster: ${gke_cluster}" + echo "Node pool: ${node_pool}" + echo "Hugepages (2Mi): ${hugepage_count}" - cat > /tmp/node-pool-config.yaml </tmp/node-pool-config.yaml </dev/null; then + if gcloud container node-pools update ${node_pool} \ + --cluster ${gke_cluster} \ + --region ${gke_location} \ + --project ${gke_project} \ + --system-config-from-file=/tmp/node-pool-config.yaml 2>/dev/null; then - echo "Node pool updated (regional cluster)" + echo "Node pool updated (regional cluster)" - elif gcloud container node-pools update ${node_pool} \ - --cluster ${gke_cluster} \ - --zone ${gke_zone} \ - --project ${gke_project} \ - --system-config-from-file=/tmp/node-pool-config.yaml 2>/dev/null; then + elif gcloud container node-pools update ${node_pool} \ + --cluster ${gke_cluster} \ + --zone ${gke_zone} \ + --project ${gke_project} \ + --system-config-from-file=/tmp/node-pool-config.yaml 2>/dev/null; then - echo "Node pool updated (zonal cluster)" - else - echo "Failed to update node pool" - rm -f /tmp/node-pool-config.yaml - return 1 - fi + echo "Node pool updated (zonal cluster)" + else + echo "Failed to update node pool" + rm -f /tmp/node-pool-config.yaml + return 1 + fi - echo "Waiting for nodes to restart..." - sleep 60 - kubectl wait --for=condition=Ready nodes --all --timeout=300s + echo "Waiting for nodes to restart..." + sleep 60 + kubectl wait --for=condition=Ready nodes --all --timeout=300s - rm -f /tmp/node-pool-config.yaml - echo "Hugepages configured on GKE" - return 0 + rm -f /tmp/node-pool-config.yaml + echo "Hugepages configured on GKE" + return 0 } enable_hugepages_eks() { - local hugepage_count=$1 + local hugepage_count=$1 - echo "Configuring hugepages on EKS" + echo "Configuring hugepages on EKS" - if verify_hugepages_on_nodes; then - echo "Hugepages already configured" - return 0 - fi + if verify_hugepages_on_nodes; then + echo "Hugepages already configured" + return 0 + fi } enable_hugepages_aks() { - local hugepage_count="${1:-2048}" - local nodepool_name="${AKS_HUGEPAGES_NODEPOOL:-hp2m}" - local vm_size="${AKS_HUGEPAGES_VM_SIZE:-Standard_D4_v2}" - local node_count="${AKS_HUGEPAGES_NODE_COUNT:-1}" - - echo "Checking hugepages on AKS..." + local hugepage_count="${1:-2048}" + local nodepool_name="${AKS_HUGEPAGES_NODEPOOL:-hp2m}" + local vm_size="${AKS_HUGEPAGES_VM_SIZE:-Standard_D4_v2}" + local node_count="${AKS_HUGEPAGES_NODE_COUNT:-1}" - if verify_hugepages_on_nodes 2>/dev/null; then - echo "Hugepages already configured" - return 0 - fi + echo "Checking hugepages on AKS..." - local cluster_name - node_rg="$(kubectl get nodes -o jsonpath='{.items[0].metadata.labels.kubernetes\.azure\.com/cluster}' 2>/dev/null || true)" - [[ -n "$node_rg" ]] || return 1 + if verify_hugepages_on_nodes 2>/dev/null; then + echo "Hugepages already configured" + return 0 + fi + local cluster_name + node_rg="$(kubectl get nodes -o jsonpath='{.items[0].metadata.labels.kubernetes\.azure\.com/cluster}' 2>/dev/null || true)" + [[ -n $node_rg ]] || return 1 - aks_id="$(az aks list --subscription "${AZURE_SUBSCRIPTION:-eng-cloud-dev}" \ - --query "[?nodeResourceGroup=='$node_rg'] | [0].id" \ - -o tsv 2>/dev/null || true)" - [[ -n "$aks_id" ]] || return 1 + aks_id="$(az aks list --subscription "${AZURE_SUBSCRIPTION:-eng-cloud-dev}" \ + --query "[?nodeResourceGroup=='$node_rg'] | [0].id" \ + -o tsv 2>/dev/null || true)" + [[ -n $aks_id ]] || return 1 - cluster_name="$(echo "$aks_id" | sed -E 's|.*/managedClusters/([^/]+)$|\1|I')" - [[ -n "$cluster_name" ]] || return 1 + cluster_name="$(echo "$aks_id" | sed -E 's|.*/managedClusters/([^/]+)$|\1|I')" + [[ -n $cluster_name ]] || return 1 - if [[ -z "${cluster_name}" ]]; then - echo "AKS: can't detect cluster name from node labels." - echo "Skipping hugepages test." - return 1 - fi + if [[ -z ${cluster_name} ]]; then + echo "AKS: can't detect cluster name from node labels." + echo "Skipping hugepages test." + return 1 + fi - echo "AKS cluster detected: ${cluster_name}" - - if ! az aks nodepool show -g percona-operators --cluster-name "${cluster_name}" -n "${nodepool_name}" >/dev/null 2>&1; then - echo "Creating nodepool '${nodepool_name}' (${vm_size}, count=${node_count}) with label hugepages=enabled..." - az aks nodepool add \ - --subscription "${AZURE_SUBSCRIPTION:-eng-cloud-dev}" \ - -g "${AKS_RG:-percona-operators}" \ - --cluster-name "${cluster_name}" \ - -n "${nodepool_name}" \ - --node-count "${node_count}" \ - --node-vm-size "${vm_size}" \ - --labels hugepages=enabled \ - --mode User - else - echo "Nodepool '${nodepool_name}' already exists." - fi + echo "AKS cluster detected: ${cluster_name}" + + if ! az aks nodepool show -g percona-operators --cluster-name "${cluster_name}" -n "${nodepool_name}" >/dev/null 2>&1; then + echo "Creating nodepool '${nodepool_name}' (${vm_size}, count=${node_count}) with label hugepages=enabled..." + az aks nodepool add \ + --subscription "${AZURE_SUBSCRIPTION:-eng-cloud-dev}" \ + -g "${AKS_RG:-percona-operators}" \ + --cluster-name "${cluster_name}" \ + -n "${nodepool_name}" \ + --node-count "${node_count}" \ + --node-vm-size "${vm_size}" \ + --labels hugepages=enabled \ + --mode User + else + echo "Nodepool '${nodepool_name}' already exists." + fi - echo "Waiting for hugepages node(s) to be Ready..." - kubectl wait node -l hugepages=enabled --for=condition=Ready --timeout=15m || { - echo "AKS: hugepages node(s) not ready in time. Skipping test." - return 1 - } + echo "Waiting for hugepages node(s) to be Ready..." + kubectl wait node -l hugepages=enabled --for=condition=Ready --timeout=15m || { + echo "AKS: hugepages node(s) not ready in time. Skipping test." + return 1 + } - echo "Applying DaemonSet to allocate hugepages on hugepages=enabled nodes (HP_2M=${hugepage_count})..." - cat </dev/null; then - echo "Hugepages configured successfully" - return 0 - fi + echo "Re-checking hugepages on nodes..." + if verify_hugepages_on_nodes 2>/dev/null; then + echo "Hugepages configured successfully" + return 0 + fi - echo "AKS: Hugepages still not visible after configuration." - echo "Skipping hugepages test." - return 1 + echo "AKS: Hugepages still not visible after configuration." + echo "Skipping hugepages test." + return 1 } enable_hugepages_openshift() { - local hugepage_count=$1 + local hugepage_count=$1 - echo "Configuring hugepages on OpenShift" + echo "Configuring hugepages on OpenShift" - if verify_hugepages_on_nodes; then - echo "Hugepages already configured" - return 0 - fi + if verify_hugepages_on_nodes; then + echo "Hugepages already configured" + return 0 + fi - echo "Creating MachineConfig..." + echo "Creating MachineConfig..." - cat < Date: Tue, 3 Feb 2026 15:37:37 +0100 Subject: [PATCH 269/300] add test run --- e2e-tests/run-pr.csv | 1 + e2e-tests/run-release.csv | 1 + 2 files changed, 2 insertions(+) diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 358ce44987..fd2a9eb155 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -6,6 +6,7 @@ database-init-sql demand-backup finalizers init-deploy +huge-pages monitoring monitoring-pmm3 one-pod diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 5a53e2617b..1de57901ae 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -6,6 +6,7 @@ database-init-sql demand-backup finalizers init-deploy +huge-pages major-upgrade monitoring monitoring-pmm3 From d7cbbb1c13db35a8c65ce9ab244d79c7d637d99a Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 4 Feb 2026 11:47:50 +0100 Subject: [PATCH 270/300] fix PR comments --- e2e-tests/functions | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e-tests/functions b/e2e-tests/functions index 50e4b3d202..5206e401ac 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -1413,7 +1413,6 @@ EOF } enable_hugepages_eks() { - local hugepage_count=$1 echo "Configuring hugepages on EKS" From b36fc5324a5de98eed5a83a9315a7b2e69832c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valmira=20Nogueira=20Corr=C3=AAa?= Date: Wed, 4 Feb 2026 09:48:28 -0300 Subject: [PATCH 271/300] Update test dependencies (#1423) * Update GKE version to 1.32 * Update test dependencies and Groovy functions --- Jenkinsfile | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ae8fb6136c..7af7d55d18 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -16,7 +16,7 @@ void createCluster(String CLUSTER_SUFFIX) { --preemptible \ --zone=${region} \ --machine-type='n1-standard-4' \ - --cluster-version='1.31' \ + --cluster-version='1.32' \ --num-nodes=3 \ --labels='delete-cluster-after-hours=6' \ --disk-size=30 \ @@ -91,7 +91,7 @@ void pushLogFile(String FILE_NAME) { def LOG_FILE_PATH="e2e-tests/logs/${FILE_NAME}.log" def LOG_FILE_NAME="${FILE_NAME}.log" echo "Push logfile $LOG_FILE_NAME file to S3!" - withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AMI/OVF', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { + withCredentials([aws(credentialsId: 'AMI/OVF', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { sh """ S3_PATH=s3://percona-jenkins-artifactory-public/\$JOB_NAME/\$(git rev-parse --short HEAD) aws s3 ls \$S3_PATH/${LOG_FILE_NAME} || : @@ -103,7 +103,7 @@ void pushLogFile(String FILE_NAME) { void pushArtifactFile(String FILE_NAME) { echo "Push $FILE_NAME file to S3!" - withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AMI/OVF', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { + withCredentials([aws(credentialsId: 'AMI/OVF', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { sh """ touch ${FILE_NAME} S3_PATH=s3://percona-jenkins-artifactory/\$JOB_NAME/\$(git rev-parse --short HEAD) @@ -128,7 +128,7 @@ void initTests() { void markPassedTests() { echo "Marking passed tests in the tests map!" - withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AMI/OVF', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { + withCredentials([aws(credentialsId: 'AMI/OVF', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { sh """ aws s3 ls "s3://percona-jenkins-artifactory/${JOB_NAME}/${env.GIT_SHORT_COMMIT}/" || : """ @@ -287,7 +287,7 @@ void prepareNode() { sudo curl -sLo /usr/local/bin/kubectl https://dl.k8s.io/release/\$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl && sudo chmod +x /usr/local/bin/kubectl kubectl version --client --output=yaml - curl -fsSL https://get.helm.sh/helm-v3.18.3-linux-amd64.tar.gz | sudo tar -C /usr/local/bin --strip-components 1 -xzf - linux-amd64/helm + curl -fsSL https://get.helm.sh/helm-v3.20.0-linux-amd64.tar.gz | sudo tar -C /usr/local/bin --strip-components 1 -xzf - linux-amd64/helm sudo curl -fsSL https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 -o /usr/local/bin/yq && sudo chmod +x /usr/local/bin/yq sudo curl -fsSL https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux64 -o /usr/local/bin/jq && sudo chmod +x /usr/local/bin/jq @@ -298,8 +298,8 @@ void prepareNode() { kubectl krew install assert - # v0.22.0 kuttl version - kubectl krew install --manifest-url https://raw.githubusercontent.com/kubernetes-sigs/krew-index/02d5befb2bc9554fdcd8386b8bfbed2732d6802e/plugins/kuttl.yaml + # v0.24.0 kuttl version + kubectl krew install --manifest-url https://raw.githubusercontent.com/kubernetes-sigs/krew-index/b913fddcbdb8e7d2b3d837ec159460671bb22796/plugins/kuttl.yaml echo \$(kubectl kuttl --version) is installed sudo tee /etc/yum.repos.d/google-cloud-sdk.repo << EOF @@ -467,7 +467,7 @@ pipeline { mkdir -p $(dirname ${docker_tag_file}) echo ${DOCKER_TAG} > "${docker_tag_file}" sg docker -c " - docker login -u '${USER}' -p '${PASS}' + echo '\$PASS' | docker login -u '\$USER' --password-stdin export RELEASE=0 export IMAGE=\$DOCKER_TAG docker buildx create --use @@ -589,7 +589,7 @@ pipeline { } } makeReport() - step([$class: 'JUnitResultArchiver', testResults: '*.xml', healthScaleFactor: 1.0]) + junit testResults: '*.xml', healthScaleFactor: 1.0 archiveArtifacts '*.xml' unstash 'IMAGE' From 44b40cdc9f957f1322758cb111f1b85b505be7c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 00:57:59 +0200 Subject: [PATCH 272/300] CLOUD-727: Bump github.com/onsi/gomega from 1.38.3 to 1.39.1 (#1432) * CLOUD-727: Bump github.com/onsi/gomega from 1.38.3 to 1.39.1 Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.38.3 to 1.39.1. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.38.3...v1.39.1) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-version: 1.39.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * bump k8s version * remove pr-badge.yml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan --- .github/pr-badge.yml | 5 ----- go.mod | 6 +++--- go.sum | 12 ++++++------ 3 files changed, 9 insertions(+), 14 deletions(-) delete mode 100644 .github/pr-badge.yml diff --git a/.github/pr-badge.yml b/.github/pr-badge.yml deleted file mode 100644 index b3ecc7f204..0000000000 --- a/.github/pr-badge.yml +++ /dev/null @@ -1,5 +0,0 @@ -label: "JIRA" -url: "https://jira.percona.com/browse/$issuePrefix" -message: "$issuePrefix" -color: "green" -when: "$issuePrefix" diff --git a/go.mod b/go.mod index 900090711b..6e53067607 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,8 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.8.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 - github.com/onsi/ginkgo/v2 v2.27.5 - github.com/onsi/gomega v1.38.3 + github.com/onsi/ginkgo/v2 v2.28.0 + github.com/onsi/gomega v1.39.1 github.com/pganalyze/pg_query_go/v6 v6.1.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 @@ -93,7 +93,7 @@ require ( github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.7.0 // indirect - github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect + github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect diff --git a/go.sum b/go.sum index e17a06673f..2b71e0f330 100644 --- a/go.sum +++ b/go.sum @@ -116,8 +116,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= -github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= @@ -169,10 +169,10 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE= -github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= -github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM= -github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= +github.com/onsi/ginkgo/v2 v2.28.0 h1:Rrf+lVLmtlBIKv6KrIGJCjyY8N36vDVcutbGJkyqjJc= +github.com/onsi/ginkgo/v2 v2.28.0/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= From 75a11d5e2d8f803828bad41480067d2753228047 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:36:20 +0200 Subject: [PATCH 273/300] CLOUD-727: Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#1428) Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.64.0 to 0.65.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.64.0...zpages/v0.65.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp dependency-version: 0.65.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 6e53067607..37ff6386e5 100644 --- a/go.mod +++ b/go.mod @@ -21,13 +21,13 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.34.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 - go.opentelemetry.io/otel v1.39.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 + go.opentelemetry.io/otel v1.40.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 - go.opentelemetry.io/otel/sdk v1.39.0 - go.opentelemetry.io/otel/trace v1.39.0 + go.opentelemetry.io/otel/sdk v1.40.0 + go.opentelemetry.io/otel/trace v1.40.0 go.uber.org/zap v1.27.1 golang.org/x/crypto v0.47.0 google.golang.org/grpc v1.77.0 @@ -118,7 +118,7 @@ require ( go.mongodb.org/mongo-driver v1.17.6 // indirect go.nhat.io/matcher/v2 v2.0.0 // indirect go.nhat.io/wait v0.1.0 // indirect - go.opentelemetry.io/otel/metric v1.39.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.49.0 // indirect diff --git a/go.sum b/go.sum index 2b71e0f330..d2e436c3e3 100644 --- a/go.sum +++ b/go.sum @@ -237,24 +237,24 @@ go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= go.nhat.io/wait v0.1.0/go.mod h1:+ijMghc9/9zXi+HDcs49HNReprvXOZha2Q3jTOtqJrE= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ= -go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= -go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0 h1:8UPA4IbVZxpsD76ihGOQiFml99GPAEZLohDXvqHdi6U= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.39.0/go.mod h1:MZ1T/+51uIVKlRzGw1Fo46KEWThjlCBZKl2LzY5nv4g= -go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= -go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= -go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= -go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= -go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= From 6f3fc9f061cf89a7b1ee8655bd162a28f8681afb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:40:22 +0200 Subject: [PATCH 274/300] CLOUD-727: Bump github.com/pganalyze/pg_query_go/v6 from 6.1.0 to 6.2.2 (#1434) Bumps [github.com/pganalyze/pg_query_go/v6](https://github.com/pganalyze/pg_query_go) from 6.1.0 to 6.2.2. - [Changelog](https://github.com/pganalyze/pg_query_go/blob/main/CHANGELOG.md) - [Commits](https://github.com/pganalyze/pg_query_go/compare/v6.1.0...v6.2.2) --- updated-dependencies: - dependency-name: github.com/pganalyze/pg_query_go/v6 dependency-version: 6.2.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 37ff6386e5..968f585c7b 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 github.com/onsi/ginkgo/v2 v2.28.0 github.com/onsi/gomega v1.39.1 - github.com/pganalyze/pg_query_go/v6 v6.1.0 + github.com/pganalyze/pg_query_go/v6 v6.2.2 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.3 github.com/xdg-go/stringprep v1.0.4 diff --git a/go.sum b/go.sum index d2e436c3e3..50d644a509 100644 --- a/go.sum +++ b/go.sum @@ -103,14 +103,12 @@ github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -173,8 +171,8 @@ github.com/onsi/ginkgo/v2 v2.28.0 h1:Rrf+lVLmtlBIKv6KrIGJCjyY8N36vDVcutbGJkyqjJc github.com/onsi/ginkgo/v2 v2.28.0/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= -github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= -github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50= +github.com/pganalyze/pg_query_go/v6 v6.2.2 h1:O0L6zMC226R82RF3X5n0Ki6HjytDsoAzuzp4ATVAHNo= +github.com/pganalyze/pg_query_go/v6 v6.2.2/go.mod h1:Cn6+j4870kJz3iYNsb0VsNG04vpSWgEvBwc590J4qD0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -311,7 +309,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= @@ -322,8 +319,6 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From c420eab90b72963fe2fc11faabc07cc131ca0037 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:42:35 +0200 Subject: [PATCH 275/300] CLOUD-727: Bump github.com/grpc-ecosystem/grpc-gateway/v2 (#1431) Bumps [github.com/grpc-ecosystem/grpc-gateway/v2](https://github.com/grpc-ecosystem/grpc-gateway) from 2.27.3 to 2.27.7. - [Release notes](https://github.com/grpc-ecosystem/grpc-gateway/releases) - [Commits](https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.27.3...v2.27.7) --- updated-dependencies: - dependency-name: github.com/grpc-ecosystem/grpc-gateway/v2 dependency-version: 2.27.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 968f585c7b..92ad9a6a51 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( go.opentelemetry.io/otel/trace v1.40.0 go.uber.org/zap v1.27.1 golang.org/x/crypto v0.47.0 - google.golang.org/grpc v1.77.0 + google.golang.org/grpc v1.78.0 gotest.tools/v3 v3.5.2 k8s.io/api v0.35.0 k8s.io/apiextensions-apiserver v0.35.0 @@ -94,7 +94,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -122,7 +122,7 @@ require ( go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.49.0 // indirect - golang.org/x/oauth2 v0.32.0 // indirect + golang.org/x/oauth2 v0.34.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.40.0 // indirect golang.org/x/term v0.39.0 // indirect @@ -130,9 +130,9 @@ require ( golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.41.0 gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/protobuf v1.36.10 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 50d644a509..46e618a8ab 100644 --- a/go.sum +++ b/go.sum @@ -122,8 +122,8 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII= github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= @@ -277,8 +277,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= -golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= @@ -313,14 +313,14 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= -google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 3c42676f2f08f7671496a5b05cfe040e00a7019a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:44:15 +0200 Subject: [PATCH 276/300] CLOUD-727: Bump github.com/onsi/ginkgo/v2 from 2.27.5 to 2.28.1 (#1430) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.27.5 to 2.28.1. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.27.5...v2.28.1) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-version: 2.28.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 92ad9a6a51..8f75a3e446 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/go-version v1.8.0 github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 - github.com/onsi/ginkgo/v2 v2.28.0 + github.com/onsi/ginkgo/v2 v2.28.1 github.com/onsi/gomega v1.39.1 github.com/pganalyze/pg_query_go/v6 v6.2.2 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 46e618a8ab..d94c3394d2 100644 --- a/go.sum +++ b/go.sum @@ -167,8 +167,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo/v2 v2.28.0 h1:Rrf+lVLmtlBIKv6KrIGJCjyY8N36vDVcutbGJkyqjJc= -github.com/onsi/ginkgo/v2 v2.28.0/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= +github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/pganalyze/pg_query_go/v6 v6.2.2 h1:O0L6zMC226R82RF3X5n0Ki6HjytDsoAzuzp4ATVAHNo= From c9760c0fa1c8ae54232ff2bfe635a2da81033c30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:46:27 +0200 Subject: [PATCH 277/300] CLOUD-727: Bump github.com/golang-jwt/jwt/v5 from 5.3.0 to 5.3.1 (#1427) Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.3.0 to 5.3.1. - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Commits](https://github.com/golang-jwt/jwt/compare/v5.3.0...v5.3.1) --- updated-dependencies: - dependency-name: github.com/golang-jwt/jwt/v5 dependency-version: 5.3.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8f75a3e446..51db43406d 100644 --- a/go.mod +++ b/go.mod @@ -90,7 +90,7 @@ require ( github.com/go-openapi/jsonreference v0.21.3 // indirect github.com/go-openapi/loads v0.23.2 // indirect github.com/go-openapi/spec v0.22.1 // indirect - github.com/golang-jwt/jwt/v5 v5.3.0 + github.com/golang-jwt/jwt/v5 v5.3.1 github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect diff --git a/go.sum b/go.sum index d94c3394d2..e224da8492 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,8 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= -github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= From d8d61beadd3e94f410be792465805858715c54e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:48:38 +0200 Subject: [PATCH 278/300] CLOUD-727: Bump sigs.k8s.io/controller-runtime from 0.22.4 to 0.23.1 (#1420) Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.22.4 to 0.23.1. - [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases) - [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.22.4...v0.23.1) --- updated-dependencies: - dependency-name: sigs.k8s.io/controller-runtime dependency-version: 0.23.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 51db43406d..348a4b4453 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( k8s.io/apimachinery v0.35.0 k8s.io/client-go v0.35.0 k8s.io/component-base v0.35.0 - sigs.k8s.io/controller-runtime v0.22.4 + sigs.k8s.io/controller-runtime v0.23.1 sigs.k8s.io/yaml v1.6.0 ) @@ -71,7 +71,7 @@ require ( golang.org/x/mod v0.32.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect ) require ( diff --git a/go.sum b/go.sum index e224da8492..4d52d0c3ec 100644 --- a/go.sum +++ b/go.sum @@ -354,13 +354,13 @@ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZ k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A= -sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8= +sigs.k8s.io/controller-runtime v0.23.1 h1:TjJSM80Nf43Mg21+RCy3J70aj/W6KyvDtOlpKf+PupE= +sigs.k8s.io/controller-runtime v0.23.1/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 h1:2WOzJpHUBVrrkDjU4KBT8n5LDcj824eX0I5UKcgeRUs= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= From 48a91ff46c038776862476551b24f474f57556c4 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Tue, 10 Feb 2026 12:49:34 +0200 Subject: [PATCH 279/300] K8SPG-822: add `builtin-extensions` e2e test (#1397) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * K8SPG-822: add `builtin-extensions` e2e test https://perconadev.atlassian.net/browse/K8SPG-822 * delete `pgvector-extension` e2e tests * check if all extensions work properly --------- Co-authored-by: Valmira Nogueira Corrêa Co-authored-by: Viacheslav Sarzhan --- e2e-tests/functions | 116 +++++++-------- e2e-tests/run-minikube.csv | 1 - e2e-tests/run-pr.csv | 2 +- e2e-tests/run-release.csv | 2 +- .../00-assert.yaml | 0 .../00-deploy-operator.yaml | 2 + .../tests/builtin-extensions/01-assert.yaml | 135 ++++++++++++++++++ .../01-create-cluster.yaml | 3 +- .../tests/builtin-extensions/02-assert.yaml | 13 ++ .../02-check-extensions.yaml | 13 ++ .../tests/builtin-extensions/03-assert.yaml | 135 ++++++++++++++++++ .../03-install-all-ext.yaml | 19 +++ .../tests/builtin-extensions/04-assert.yaml | 17 +++ .../04-check-extensions.yaml | 13 ++ .../05-check-ext-funcs.yaml | 58 ++++++++ .../tests/builtin-extensions/06-assert.yaml | 135 ++++++++++++++++++ .../06-uninstall-all-ext.yaml | 12 ++ .../tests/builtin-extensions/07-assert.yaml | 11 ++ .../07-check-extensions.yaml | 13 ++ .../99-remove-cluster-gracefully.yaml | 4 +- .../tests/pgvector-extension/01-assert.yaml | 88 ------------ ...verify-pgvector-extension-is-disabled.yaml | 18 --- .../03-enable-pgvector-extension.yaml | 13 -- ...-verify-pgvector-extension-is-enabled.yaml | 34 ----- .../05-disable-pgvector-extension.yaml | 13 -- ...verify-pgvector-extension-is-disabled.yaml | 29 ---- 26 files changed, 639 insertions(+), 260 deletions(-) rename e2e-tests/tests/{pgvector-extension => builtin-extensions}/00-assert.yaml (100%) rename e2e-tests/tests/{pgvector-extension => builtin-extensions}/00-deploy-operator.yaml (85%) create mode 100644 e2e-tests/tests/builtin-extensions/01-assert.yaml rename e2e-tests/tests/{pgvector-extension => builtin-extensions}/01-create-cluster.yaml (62%) create mode 100644 e2e-tests/tests/builtin-extensions/02-assert.yaml create mode 100644 e2e-tests/tests/builtin-extensions/02-check-extensions.yaml create mode 100644 e2e-tests/tests/builtin-extensions/03-assert.yaml create mode 100644 e2e-tests/tests/builtin-extensions/03-install-all-ext.yaml create mode 100644 e2e-tests/tests/builtin-extensions/04-assert.yaml create mode 100644 e2e-tests/tests/builtin-extensions/04-check-extensions.yaml create mode 100644 e2e-tests/tests/builtin-extensions/05-check-ext-funcs.yaml create mode 100644 e2e-tests/tests/builtin-extensions/06-assert.yaml create mode 100644 e2e-tests/tests/builtin-extensions/06-uninstall-all-ext.yaml create mode 100644 e2e-tests/tests/builtin-extensions/07-assert.yaml create mode 100644 e2e-tests/tests/builtin-extensions/07-check-extensions.yaml rename e2e-tests/tests/{pgvector-extension => builtin-extensions}/99-remove-cluster-gracefully.yaml (86%) delete mode 100644 e2e-tests/tests/pgvector-extension/01-assert.yaml delete mode 100644 e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-disabled.yaml delete mode 100644 e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml delete mode 100644 e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml delete mode 100644 e2e-tests/tests/pgvector-extension/05-disable-pgvector-extension.yaml delete mode 100644 e2e-tests/tests/pgvector-extension/06-verify-pgvector-extension-is-disabled.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index 6b2a23167e..a262ce539a 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -117,61 +117,61 @@ remove_all_finalizers() { } wait_for_ready_containers() { - local pod_prefix="$1" - local target_count="$2" - local namespace="${NAMESPACE}" - local max_wait_seconds=300 - local check_interval=5 - local elapsed_time=0 - - if [[ -z "$pod_prefix" || -z "$target_count" || -z "$namespace" ]]; then - echo "Error: Missing arguments." >&2 - echo "Usage: wait_for_ready_containers " >&2 - return 1 - fi + local pod_prefix="$1" + local target_count="$2" + local namespace="${NAMESPACE}" + local max_wait_seconds=300 + local check_interval=5 + local elapsed_time=0 + + if [[ -z $pod_prefix || -z $target_count || -z $namespace ]]; then + echo "Error: Missing arguments." >&2 + echo "Usage: wait_for_ready_containers " >&2 + return 1 + fi - echo "Waiting for pods starting with '$pod_prefix' in namespace '$namespace' to have $target_count ready containers (Max ${max_wait_seconds}s)..." - - while [[ "$elapsed_time" -lt "$max_wait_seconds" ]]; do - local target_pods - # Get pods that match the prefix AND are running - target_pods=$(kubectl get pods -n "$namespace" --field-selector=status.phase=Running --output=json | \ - jq -r ".items[] | select(.metadata.name | startswith(\"$pod_prefix\")) | .metadata.name") - # If no running pods match the prefix, something might be wrong, but we'll keep waiting. - if [[ -z "$target_pods" ]]; then - echo "No running pods found with prefix '$pod_prefix'. Waiting..." - sleep "$check_interval" - elapsed_time=$((elapsed_time + check_interval)) - continue - fi - - local ready_count=0 - local total_matches=0 - - # Check each pod individually - for pod_name in $target_pods; do - total_matches=$((total_matches + 1)) - current_ready=$(kubectl get pod "$pod_name" -n "$namespace" -o json 2>/dev/null | \ - jq '.status.containerStatuses | map(select(.ready == true)) | length') - - if [[ "$current_ready" -eq "$target_count" ]]; then - ready_count=$((ready_count + 1)) - fi - done - - if [[ "$ready_count" -eq "$total_matches" ]]; then - echo "Success: All $total_matches pods now have $target_count ready containers." - return 0 - fi - - echo "Current status: $ready_count of $total_matches pods have $target_count ready containers. Waiting ${check_interval}s..." - - sleep "$check_interval" - elapsed_time=$((elapsed_time + check_interval)) - done - - echo "Error: Timeout reached! After ${max_wait_seconds} seconds, not all pods reached $target_count ready containers." >&2 - return 1 + echo "Waiting for pods starting with '$pod_prefix' in namespace '$namespace' to have $target_count ready containers (Max ${max_wait_seconds}s)..." + + while [[ $elapsed_time -lt $max_wait_seconds ]]; do + local target_pods + # Get pods that match the prefix AND are running + target_pods=$(kubectl get pods -n "$namespace" --field-selector=status.phase=Running --output=json \ + | jq -r ".items[] | select(.metadata.name | startswith(\"$pod_prefix\")) | .metadata.name") + # If no running pods match the prefix, something might be wrong, but we'll keep waiting. + if [[ -z $target_pods ]]; then + echo "No running pods found with prefix '$pod_prefix'. Waiting..." + sleep "$check_interval" + elapsed_time=$((elapsed_time + check_interval)) + continue + fi + + local ready_count=0 + local total_matches=0 + + # Check each pod individually + for pod_name in $target_pods; do + total_matches=$((total_matches + 1)) + current_ready=$(kubectl get pod "$pod_name" -n "$namespace" -o json 2>/dev/null \ + | jq '.status.containerStatuses | map(select(.ready == true)) | length') + + if [[ $current_ready -eq $target_count ]]; then + ready_count=$((ready_count + 1)) + fi + done + + if [[ $ready_count -eq $total_matches ]]; then + echo "Success: All $total_matches pods now have $target_count ready containers." + return 0 + fi + + echo "Current status: $ready_count of $total_matches pods have $target_count ready containers. Waiting ${check_interval}s..." + + sleep "$check_interval" + elapsed_time=$((elapsed_time + check_interval)) + done + + echo "Error: Timeout reached! After ${max_wait_seconds} seconds, not all pods reached $target_count ready containers." >&2 + return 1 } destroy_operator() { @@ -255,7 +255,7 @@ deploy_s3_secrets() { yq eval '.stringData["credentials.json"]' ${TESTS_CONFIG_DIR}/cloud-secret-minio-gw.yml >${TEMP_DIR}/gcs-key.json kubectl -n "${NAMESPACE}" create secret generic "${test_name}-pgbackrest-secrets" --from-file=cloud.conf="${TEMP_DIR}/pgbackrest-secret.ini" --from-file=gcs-key.json=${TEMP_DIR}/gcs-key.json ;; - "custom-extensions" | "major-upgrade") + "custom-extensions" | "major-upgrade" | "builtin-extensions") kubectl -n "${NAMESPACE}" apply -f "${TESTS_CONFIG_DIR}/cloud-secret.yml" kubectl -n "${NAMESPACE}" apply -f "${TESTS_CONFIG_DIR}/minio-secret.yml" ;; @@ -1097,7 +1097,7 @@ deploy_cert_manager() { echo 'deploy cert manager' kubectl create namespace cert-manager || : kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true || : - kubectl apply -f "https://github.com/jetstack/cert-manager/releases/download/v${CERT_MANAGER_VER}/cert-manager.yaml" --validate=false > /dev/null 2>&1 || : + kubectl apply -f "https://github.com/jetstack/cert-manager/releases/download/v${CERT_MANAGER_VER}/cert-manager.yaml" --validate=false >/dev/null 2>&1 || : kubectl wait deployment cert-manager cert-manager-webhook cert-manager-cainjector \ --for=condition=available \ @@ -1111,8 +1111,8 @@ deploy_cert_manager() { } destroy_cert_manager() { - kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v${CERT_MANAGER_VER}/cert-manager.yaml > /dev/null 2>&1 || : - kubectl delete --grace-period=0 --force=true namespace cert-manager > /dev/null 2>&1 || : + kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v${CERT_MANAGER_VER}/cert-manager.yaml >/dev/null 2>&1 || : + kubectl delete --grace-period=0 --force=true namespace cert-manager >/dev/null 2>&1 || : } get_container_image() { diff --git a/e2e-tests/run-minikube.csv b/e2e-tests/run-minikube.csv index 0a46f447c4..2545653a67 100644 --- a/e2e-tests/run-minikube.csv +++ b/e2e-tests/run-minikube.csv @@ -5,7 +5,6 @@ database-init-sql demand-backup finalizers init-deploy -pgvector-extension one-pod operator-self-healing scaling diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 358ce44987..34949807ac 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -1,4 +1,5 @@ backup-enable-disable +builtin-extensions custom-envs custom-extensions custom-tls @@ -10,7 +11,6 @@ monitoring monitoring-pmm3 one-pod operator-self-healing -pgvector-extension pitr scaling scheduled-backup diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 5a53e2617b..ab8b326df9 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -1,4 +1,5 @@ backup-enable-disable +builtin-extensions custom-envs custom-extensions custom-tls @@ -11,7 +12,6 @@ monitoring monitoring-pmm3 one-pod operator-self-healing -pgvector-extension pitr scaling scheduled-backup diff --git a/e2e-tests/tests/pgvector-extension/00-assert.yaml b/e2e-tests/tests/builtin-extensions/00-assert.yaml similarity index 100% rename from e2e-tests/tests/pgvector-extension/00-assert.yaml rename to e2e-tests/tests/builtin-extensions/00-assert.yaml diff --git a/e2e-tests/tests/pgvector-extension/00-deploy-operator.yaml b/e2e-tests/tests/builtin-extensions/00-deploy-operator.yaml similarity index 85% rename from e2e-tests/tests/pgvector-extension/00-deploy-operator.yaml rename to e2e-tests/tests/builtin-extensions/00-deploy-operator.yaml index 1aaca58be2..96329aabb8 100644 --- a/e2e-tests/tests/pgvector-extension/00-deploy-operator.yaml +++ b/e2e-tests/tests/builtin-extensions/00-deploy-operator.yaml @@ -11,3 +11,5 @@ commands: deploy_operator deploy_client + deploy_s3_secrets + deploy_minio diff --git a/e2e-tests/tests/builtin-extensions/01-assert.yaml b/e2e-tests/tests/builtin-extensions/01-assert.yaml new file mode 100644 index 0000000000..fa5975dc7f --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/01-assert.yaml @@ -0,0 +1,135 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 180 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: builtin-extensions-repo-host + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: builtin-extensions-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: builtin-extensions + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: builtin-extensions +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml b/e2e-tests/tests/builtin-extensions/01-create-cluster.yaml similarity index 62% rename from e2e-tests/tests/pgvector-extension/01-create-cluster.yaml rename to e2e-tests/tests/builtin-extensions/01-create-cluster.yaml index 4764045e8a..abe1d5a61a 100644 --- a/e2e-tests/tests/pgvector-extension/01-create-cluster.yaml +++ b/e2e-tests/tests/builtin-extensions/01-create-cluster.yaml @@ -8,5 +8,4 @@ commands: source ../../functions - get_cr "pgvector-extension" ${RANDOM} \ - | kubectl -n "${NAMESPACE}" apply -f - + get_cr | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/builtin-extensions/02-assert.yaml b/e2e-tests/tests/builtin-extensions/02-assert.yaml new file mode 100644 index 0000000000..efce0cf400 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/02-assert.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 02-check-extensions +data: + data: |2- + pg_stat_monitor + pgaudit + plpgsql diff --git a/e2e-tests/tests/builtin-extensions/02-check-extensions.yaml b/e2e-tests/tests/builtin-extensions/02-check-extensions.yaml new file mode 100644 index 0000000000..1f29c2b415 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/02-check-extensions.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres) -c "\c postgres" -c "SELECT extname FROM pg_extension ORDER BY extname") + + kubectl create configmap -n "${NAMESPACE}" 02-check-extensions --from-literal=data="${data}" diff --git a/e2e-tests/tests/builtin-extensions/03-assert.yaml b/e2e-tests/tests/builtin-extensions/03-assert.yaml new file mode 100644 index 0000000000..8bf4703591 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/03-assert.yaml @@ -0,0 +1,135 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 180 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: builtin-extensions-repo-host + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: builtin-extensions-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: builtin-extensions + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 2 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: builtin-extensions +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/builtin-extensions/03-install-all-ext.yaml b/e2e-tests/tests/builtin-extensions/03-install-all-ext.yaml new file mode 100644 index 0000000000..4446a35e36 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/03-install-all-ext.yaml @@ -0,0 +1,19 @@ +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: builtin-extensions +spec: + patroni: + dynamicConfiguration: + postgresql: + parameters: + pgaudit.log: 'ddl,write,role' + pgaudit.log_level: 'warning' + logging_collector: 'off' + extensions: + builtin: + pg_stat_monitor: true + pg_stat_statements: true + pg_audit: true + pgvector: true + pg_repack: true diff --git a/e2e-tests/tests/builtin-extensions/04-assert.yaml b/e2e-tests/tests/builtin-extensions/04-assert.yaml new file mode 100644 index 0000000000..a91709b7b8 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/04-assert.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 04-check-extensions +data: + data: |2- + pg_repack + pg_stat_monitor + pg_stat_statements + pgaudit + plpgsql + vector + diff --git a/e2e-tests/tests/builtin-extensions/04-check-extensions.yaml b/e2e-tests/tests/builtin-extensions/04-check-extensions.yaml new file mode 100644 index 0000000000..c5b0581a9d --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/04-check-extensions.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres) -c "\c postgres" -c "SELECT extname FROM pg_extension ORDER BY extname") + + kubectl create configmap -n "${NAMESPACE}" 04-check-extensions --from-literal=data="${data}" diff --git a/e2e-tests/tests/builtin-extensions/05-check-ext-funcs.yaml b/e2e-tests/tests/builtin-extensions/05-check-ext-funcs.yaml new file mode 100644 index 0000000000..51e7c377fd --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/05-check-ext-funcs.yaml @@ -0,0 +1,58 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + sleep 30 + + # pg_stat_monitor + run_psql_local \ + "SELECT pg_stat_monitor_reset();" \ + "postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres)/postgres" + + # pg_stat_statements + run_psql_local \ + "SELECT pg_stat_statements_reset();" \ + "postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres)/postgres" + + # pg_audit + run_psql_local \ + "CREATE TEMP TABLE pgaudit_test(x int);DROP TABLE pgaudit_test;" \ + "postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres)/postgres" + + if [[ $(kubectl logs -n ${NAMESPACE} -l "postgres-operator.crunchydata.com/instance-set=instance1" --tail=-1 | grep -c 'AUDIT:') == 0 ]]; then + echo "Expected `AUDIT:` logs" + exit 1 + fi + + # pgvector + run_psql_local \ + "SELECT '\''[1,2,3]'\''::vector <-> '\''[3,2,1]'\''::vector;" \ + "postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres)/postgres" + + # pg_repack + prev_relfilenode=$(run_psql_local \ + "CREATE TABLE public.repack_smoke(id int PRIMARY KEY, t text); + INSERT INTO public.repack_smoke + SELECT i, repeat('\''x'\'',200) FROM generate_series(1,5000) i; + DELETE FROM public.repack_smoke WHERE id %% 2 = 0; + SELECT relfilenode FROM pg_class WHERE oid='\''public.repack_smoke'\''::regclass;" \ + "postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres)/postgres") + + kubectl -n ${NAMESPACE} exec $(get_client_pod) -- \ + pg_repack -d "postgres://postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres)/postgres" -t "public.repack_smoke" + + cur_relfilenode=$(run_psql_local \ + "SELECT relfilenode FROM pg_class WHERE oid='\''public.repack_smoke'\''::regclass;" \ + "postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres)/postgres") + if [[ $prev_relfilenode == $cur_relfilenode ]]; then + echo "pg_repack check failed" + exit 1 + fi + + timeout: 360 + diff --git a/e2e-tests/tests/builtin-extensions/06-assert.yaml b/e2e-tests/tests/builtin-extensions/06-assert.yaml new file mode 100644 index 0000000000..a7cd11690d --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/06-assert.yaml @@ -0,0 +1,135 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 180 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: builtin-extensions-repo-host + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: builtin-extensions-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: builtin-extensions + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: builtin-extensions + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: builtin-extensions + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 3 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: builtin-extensions +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/builtin-extensions/06-uninstall-all-ext.yaml b/e2e-tests/tests/builtin-extensions/06-uninstall-all-ext.yaml new file mode 100644 index 0000000000..8321692d31 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/06-uninstall-all-ext.yaml @@ -0,0 +1,12 @@ +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: builtin-extensions +spec: + extensions: + builtin: + pg_stat_monitor: false + pg_stat_statements: false + pg_audit: false + pgvector: false + pg_repack: false diff --git a/e2e-tests/tests/builtin-extensions/07-assert.yaml b/e2e-tests/tests/builtin-extensions/07-assert.yaml new file mode 100644 index 0000000000..9c0c6c13a6 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/07-assert.yaml @@ -0,0 +1,11 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 06-check-extensions +data: + data: |2- + plpgsql diff --git a/e2e-tests/tests/builtin-extensions/07-check-extensions.yaml b/e2e-tests/tests/builtin-extensions/07-check-extensions.yaml new file mode 100644 index 0000000000..2b918afa27 --- /dev/null +++ b/e2e-tests/tests/builtin-extensions/07-check-extensions.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(kubectl -n ${NAMESPACE} exec $(get_client_pod) -- psql -v ON_ERROR_STOP=1 -t -q postgres://postgres:$(get_psql_user_pass builtin-extensions-pguser-postgres)@$(get_psql_user_host builtin-extensions-pguser-postgres) -c "\c postgres" -c "SELECT extname FROM pg_extension ORDER BY extname") + + kubectl create configmap -n "${NAMESPACE}" 06-check-extensions --from-literal=data="${data}" diff --git a/e2e-tests/tests/pgvector-extension/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/builtin-extensions/99-remove-cluster-gracefully.yaml similarity index 86% rename from e2e-tests/tests/pgvector-extension/99-remove-cluster-gracefully.yaml rename to e2e-tests/tests/builtin-extensions/99-remove-cluster-gracefully.yaml index 11c075f46b..76d45908dd 100644 --- a/e2e-tests/tests/pgvector-extension/99-remove-cluster-gracefully.yaml +++ b/e2e-tests/tests/builtin-extensions/99-remove-cluster-gracefully.yaml @@ -4,11 +4,11 @@ delete: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: pgvector-extension + name: builtin-extensions - apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: - name: pgvector-extension + name: builtin-extensions commands: - script: |- set -o errexit diff --git a/e2e-tests/tests/pgvector-extension/01-assert.yaml b/e2e-tests/tests/pgvector-extension/01-assert.yaml deleted file mode 100644 index 903a1768da..0000000000 --- a/e2e-tests/tests/pgvector-extension/01-assert.yaml +++ /dev/null @@ -1,88 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 300 ---- -kind: StatefulSet -apiVersion: apps/v1 -metadata: - labels: - postgres-operator.crunchydata.com/cluster: pgvector-extension - postgres-operator.crunchydata.com/data: postgres - postgres-operator.crunchydata.com/instance-set: instance1 - ownerReferences: - - apiVersion: postgres-operator.crunchydata.com/v1beta1 - kind: PostgresCluster - name: pgvector-extension - controller: true - blockOwnerDeletion: true -status: - observedGeneration: 1 - replicas: 1 - readyReplicas: 1 - updatedReplicas: 1 - collisionCount: 0 ---- -kind: Deployment -apiVersion: apps/v1 -metadata: - name: pgvector-extension-pgbouncer - labels: - postgres-operator.crunchydata.com/cluster: pgvector-extension - postgres-operator.crunchydata.com/role: pgbouncer - annotations: - deployment.kubernetes.io/revision: '1' - ownerReferences: - - apiVersion: postgres-operator.crunchydata.com/v1beta1 - kind: PostgresCluster - name: pgvector-extension - controller: true - blockOwnerDeletion: true -status: - observedGeneration: 1 - replicas: 3 - updatedReplicas: 3 - readyReplicas: 3 ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: pgvector-extension - ownerReferences: - - apiVersion: pgv2.percona.com/v2 - kind: PerconaPGCluster - name: pgvector-extension - controller: true - blockOwnerDeletion: true - finalizers: - - postgres-operator.crunchydata.com/finalizer -spec: - backups: - pgbackrest: {} -status: - instances: - - name: instance1 - readyReplicas: 3 - replicas: 3 - updatedReplicas: 3 - observedGeneration: 1 - proxy: - pgBouncer: - readyReplicas: 3 - replicas: 3 ---- -apiVersion: pgv2.percona.com/v2 -kind: PerconaPGCluster -metadata: - name: pgvector-extension -status: - pgbouncer: - ready: 3 - size: 3 - postgres: - instances: - - name: instance1 - ready: 3 - size: 3 - ready: 3 - size: 3 - state: ready diff --git a/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-disabled.yaml b/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-disabled.yaml deleted file mode 100644 index e23df8ea45..0000000000 --- a/e2e-tests/tests/pgvector-extension/02-verify-pgvector-extension-is-disabled.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - result=$(run_psql_local \ - "SELECT * FROM pg_extension WHERE extname = '\''vector'\'';" \ - "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") - - if [[ "$result" = *"vector"* ]]; then - echo "pgvector extension is not disabled by default" - exit 1 - fi - timeout: 360 diff --git a/e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml b/e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml deleted file mode 100644 index bf7276223f..0000000000 --- a/e2e-tests/tests/pgvector-extension/03-enable-pgvector-extension.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -timeout: 10 -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - get_cr "pgvector-extension" ${RANDOM} \ - | yq '.spec.extensions.builtin.pgvector=true' \ - | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml b/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml deleted file mode 100644 index c8187eff0e..0000000000 --- a/e2e-tests/tests/pgvector-extension/04-verify-pgvector-extension-is-enabled.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - retries=10 - wait_seconds=5 - - for i in $(seq 1 $retries); do - - result=$(run_psql_local \ - "SELECT * FROM pg_extension WHERE extname = '\''vector'\'';" \ - "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") - - if [[ "$result" = *"vector"* ]]; then - echo "pgvector extension is enabled, verifying extension" - run_psql_local \ - "SELECT '\''[1,2,3]'\''::vector <-> '\''[3,2,1]'\''::vector;" \ - "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres" - - exit 0 - fi - - echo "pgvector extension not enabled, retrying in $wait_seconds seconds..." - sleep $wait_seconds - done - - echo "pgvector extension is not properly enabled" - exit 1 - timeout: 360 diff --git a/e2e-tests/tests/pgvector-extension/05-disable-pgvector-extension.yaml b/e2e-tests/tests/pgvector-extension/05-disable-pgvector-extension.yaml deleted file mode 100644 index 4fdba57a92..0000000000 --- a/e2e-tests/tests/pgvector-extension/05-disable-pgvector-extension.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -timeout: 10 -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - get_cr "pgvector-extension" ${RANDOM} \ - | yq '.spec.extensions.builtin.pgvector=false' \ - | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/pgvector-extension/06-verify-pgvector-extension-is-disabled.yaml b/e2e-tests/tests/pgvector-extension/06-verify-pgvector-extension-is-disabled.yaml deleted file mode 100644 index ed129a6032..0000000000 --- a/e2e-tests/tests/pgvector-extension/06-verify-pgvector-extension-is-disabled.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - - retries=10 - wait_seconds=5 - - for i in $(seq 1 $retries); do - result=$(run_psql_local \ - "SELECT * FROM pg_extension WHERE extname = '\''vector'\'';" \ - "postgres:$(get_psql_user_pass pgvector-extension-pguser-postgres)@$(get_psql_user_host pgvector-extension-pguser-postgres)/postgres") - - if [[ "$result" != *"vector"* ]]; then - echo "pgvector extension is disabled" - exit 0 - fi - - echo "pgvector extension still present, retrying in $wait_seconds seconds..." - sleep $wait_seconds - done - - echo "pgvector extension was not properly disabled" - exit 1 - timeout: 360 From 0d2e0af415cb994f276d939ecb30aa9bdd318d2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:51:03 +0200 Subject: [PATCH 280/300] CLOUD-727: Bump github.com/sirupsen/logrus from 1.9.3 to 1.9.4 (#1415) Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.9.3 to 1.9.4. - [Release notes](https://github.com/sirupsen/logrus/releases) - [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md) - [Commits](https://github.com/sirupsen/logrus/compare/v1.9.3...v1.9.4) --- updated-dependencies: - dependency-name: github.com/sirupsen/logrus dependency-version: 1.9.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 348a4b4453..9324403777 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/onsi/gomega v1.39.1 github.com/pganalyze/pg_query_go/v6 v6.2.2 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.9.3 + github.com/sirupsen/logrus v1.9.4 github.com/xdg-go/stringprep v1.0.4 go.nhat.io/grpcmock v0.34.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 diff --git a/go.sum b/go.sum index 4d52d0c3ec..fb7bc92f97 100644 --- a/go.sum +++ b/go.sum @@ -192,8 +192,8 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= @@ -203,7 +203,6 @@ github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/swaggest/assertjson v1.10.0 h1:OYIx29UbgqjwAekKbeIO8T0XbAMyViJ8qqrVj2GQY2M= @@ -287,7 +286,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= @@ -333,7 +331,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= From 72bd50b523b54d742a11a958b85c4128d5eb0499 Mon Sep 17 00:00:00 2001 From: Julio Pasinatto Date: Tue, 10 Feb 2026 07:51:31 -0300 Subject: [PATCH 281/300] Update codeowners (#1425) Co-authored-by: Viacheslav Sarzhan --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5af2e49459..8c003e070b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ * @hors @egegunes @pooknull @nmarukovich @gkech @mayankshah1607 @oksana-grishchenko -/e2e-tests/ @jvpasinatto @eleo007 @valmiranogueira @bogdanjeler-ev @egegunes @pooknull @nmarukovich @gkech @mayankshah1607 @oksana-grishchenko -Jenkinsfile @jvpasinatto @eleo007 @valmiranogueira @bogdanjeler-ev +/e2e-tests/ @jvpasinatto @eleo007 @valmiranogueira @egegunes @pooknull @nmarukovich @gkech @mayankshah1607 @oksana-grishchenko +Jenkinsfile @jvpasinatto @eleo007 @valmiranogueira From e97aebda56f35336a178ff996dadac67dfa34643 Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Tue, 10 Feb 2026 12:54:18 +0200 Subject: [PATCH 282/300] K8SPG-758: add `PPROF_BIND_ADDRESS` env var to `operator.yaml` (#1392) * K8SPG-758: add `PPROF_BIND_ADDRESS` env var to `operator.yaml` https://perconadev.atlassian.net/browse/K8SPG-758 * make manifests --------- Co-authored-by: Viacheslav Sarzhan --- cmd/postgres-operator/main.go | 2 ++ cmd/postgres-operator/main_test.go | 11 +++++++++++ config/manager/default/manager.yaml | 2 ++ deploy/bundle.yaml | 2 ++ deploy/cw-bundle.yaml | 2 ++ deploy/cw-operator.yaml | 2 ++ deploy/operator.yaml | 2 ++ 7 files changed, 23 insertions(+) diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 6244d92223..5ee3b65193 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -334,6 +334,8 @@ func initManager(ctx context.Context) (runtime.Options, error) { } } + options.PprofBindAddress = os.Getenv("PPROF_BIND_ADDRESS") + return options, nil } diff --git a/cmd/postgres-operator/main_test.go b/cmd/postgres-operator/main_test.go index d9865d56cd..38d55b6002 100644 --- a/cmd/postgres-operator/main_test.go +++ b/cmd/postgres-operator/main_test.go @@ -137,4 +137,15 @@ func TestInitManager(t *testing.T) { }) }) }) + + t.Run("PPROF_BIND_ADDRESS", func(t *testing.T) { + options, err := initManager(ctx) + assert.NilError(t, err) + assert.DeepEqual(t, options.PprofBindAddress, "") + + t.Setenv("PPROF_BIND_ADDRESS", "pprof-addr") + options, err = initManager(ctx) + assert.NilError(t, err) + assert.DeepEqual(t, options.PprofBindAddress, "pprof-addr") + }) } diff --git a/config/manager/default/manager.yaml b/config/manager/default/manager.yaml index bc132a43cd..d7a647692b 100644 --- a/config/manager/default/manager.yaml +++ b/config/manager/default/manager.yaml @@ -37,6 +37,8 @@ spec: value: "false" - name: PGO_WORKERS value: "1" + - name: PPROF_BIND_ADDRESS + value: "0" ports: - containerPort: 8080 name: metrics diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index aa2c93d8bd..55223956cf 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -54188,6 +54188,8 @@ spec: value: "false" - name: PGO_WORKERS value: "1" + - name: PPROF_BIND_ADDRESS + value: "0" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 7c5c730043..242edba2b5 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -54186,6 +54186,8 @@ spec: value: "false" - name: PGO_WORKERS value: "1" + - name: PPROF_BIND_ADDRESS + value: "0" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 7861413845..0a75a83fc4 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -44,6 +44,8 @@ spec: value: "false" - name: PGO_WORKERS value: "1" + - name: PPROF_BIND_ADDRESS + value: "0" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/operator.yaml b/deploy/operator.yaml index c6c492333b..3595d64cfe 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -47,6 +47,8 @@ spec: value: "false" - name: PGO_WORKERS value: "1" + - name: PPROF_BIND_ADDRESS + value: "0" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: From dae160fae22fc6cae26b56234767f2bf00d615a8 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Tue, 10 Feb 2026 12:57:38 +0200 Subject: [PATCH 283/300] K8SPG-837 improve image building process (#1422) * K8SPG-837 improve image building process * add possibility of setting the base image via the build argument * bump k8s version --- build/postgres-operator/Dockerfile | 4 +++- e2e-tests/build | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index 59646d9aa4..2d0663c455 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -1,3 +1,5 @@ +ARG BASE_IMAGE=ubi10 + FROM --platform=${BUILDPLATFORM} golang:1.25 AS go_builder WORKDIR /go/src/github.com/percona/percona-postgresql-operator @@ -45,7 +47,7 @@ RUN mkdir -p build/_output/bin \ RUN ./bin/license_aggregator.sh ./cmd/...; \ cp -r ./licenses /licenses -FROM registry.access.redhat.com/ubi10/ubi-minimal AS ubi10 +FROM registry.access.redhat.com/${BASE_IMAGE}/ubi-minimal AS ubi RUN microdnf update -y && microdnf clean all -y LABEL name="Percona Postgres Operator" \ diff --git a/e2e-tests/build b/e2e-tests/build index 56a98a9573..dbd0617159 100755 --- a/e2e-tests/build +++ b/e2e-tests/build @@ -50,6 +50,7 @@ build_operator() { --build-arg GIT_BRANCH="${GIT_BRANCH}" \ --build-arg BUILD_TIME="${BUILD_TIME}" \ --build-arg GO_LDFLAGS="${GO_LDFLAGS}" \ + --build-arg BASE_IMAGE="${BASE_IMAGE:-ubi10}" \ --progress plain \ $imgresult \ $squash \ From 2a8032f571161c7daa1d8dbf3afce411a520dcc2 Mon Sep 17 00:00:00 2001 From: Mayank Shah Date: Tue, 10 Feb 2026 19:10:49 +0530 Subject: [PATCH 284/300] K8SPG-374: detect replication lag on standby (#1407) Signed-off-by: Mayank Shah --- .../pgv2.percona.com_perconapgclusters.yaml | 20 + .../postgres-readiness-check.sh | 6 +- cmd/postgres-operator/main.go | 10 +- .../pgv2.percona.com_perconapgclusters.yaml | 20 + deploy/bundle.yaml | 20 + deploy/cr.yaml | 1 + deploy/crd.yaml | 20 + deploy/cw-bundle.yaml | 20 + e2e-tests/functions | 2 +- e2e-tests/run-pr.csv | 2 + e2e-tests/run-release.csv | 2 + .../tests/standby-pgbackrest/00-assert.yaml | 24 + .../00-deploy-operator.yaml | 13 + .../tests/standby-pgbackrest/01-assert.yaml | 103 ++++ .../01-create-source-cluster.yaml | 11 + .../tests/standby-pgbackrest/02-assert.yaml | 89 +++ .../02-create-standby-cluster.yaml | 18 + .../03-standby-lockdown.yaml | 18 + .../tests/standby-pgbackrest/04-assert.yaml | 16 + .../standby-pgbackrest/04-generate-data.yaml | 17 + .../tests/standby-pgbackrest/05-assert.yaml | 15 + .../05-standby-remove-lockdown.yaml | 17 + .../tests/standby-pgbackrest/99-cleanup.yaml | 28 + .../tests/standby-streaming/00-assert.yaml | 24 + .../standby-streaming/00-deploy-operator.yaml | 13 + .../tests/standby-streaming/01-assert.yaml | 103 ++++ .../01-create-source-cluster.yaml | 11 + .../tests/standby-streaming/02-assert.yaml | 89 +++ .../02-create-standby-cluster.yaml | 20 + .../03-standby-lockdown.yaml | 22 + .../tests/standby-streaming/04-assert.yaml | 16 + .../standby-streaming/04-generate-data.yaml | 17 + .../tests/standby-streaming/05-assert.yaml | 15 + .../05-standby-remove-lockdown.yaml | 17 + .../tests/standby-streaming/99-cleanup.yaml | 28 + .../controller/postgrescluster/pgbackrest.go | 4 + .../controller/postgrescluster/postgres.go | 2 +- internal/pgmonitor/postgres.go | 2 +- internal/postgres/databases.go | 2 +- internal/postgres/exec.go | 5 +- internal/postgres/exec_test.go | 2 +- internal/postgres/users.go | 2 +- percona/controller/pgcluster/controller.go | 15 +- percona/controller/pgcluster/standby.go | 383 ++++++++++++ percona/controller/pgcluster/standby_test.go | 544 ++++++++++++++++++ percona/controller/pgcluster/status.go | 5 + percona/naming/annotations.go | 5 + .../v2/perconapgcluster_types.go | 35 +- .../v2/perconapgcluster_types_test.go | 106 ++++ .../v2/zz_generated.deepcopy.go | 51 +- .../v1beta1/pgbackrest_types.go | 33 ++ .../v1beta1/pgbackrest_types_test.go | 462 +++++++++++++++ 52 files changed, 2512 insertions(+), 13 deletions(-) create mode 100644 e2e-tests/tests/standby-pgbackrest/00-assert.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/01-assert.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/01-create-source-cluster.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/02-assert.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/02-create-standby-cluster.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/03-standby-lockdown.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/04-assert.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/04-generate-data.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/05-assert.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/05-standby-remove-lockdown.yaml create mode 100644 e2e-tests/tests/standby-pgbackrest/99-cleanup.yaml create mode 100644 e2e-tests/tests/standby-streaming/00-assert.yaml create mode 100644 e2e-tests/tests/standby-streaming/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/standby-streaming/01-assert.yaml create mode 100644 e2e-tests/tests/standby-streaming/01-create-source-cluster.yaml create mode 100644 e2e-tests/tests/standby-streaming/02-assert.yaml create mode 100644 e2e-tests/tests/standby-streaming/02-create-standby-cluster.yaml create mode 100644 e2e-tests/tests/standby-streaming/03-standby-lockdown.yaml create mode 100644 e2e-tests/tests/standby-streaming/04-assert.yaml create mode 100644 e2e-tests/tests/standby-streaming/04-generate-data.yaml create mode 100644 e2e-tests/tests/standby-streaming/05-assert.yaml create mode 100644 e2e-tests/tests/standby-streaming/05-standby-remove-lockdown.yaml create mode 100644 e2e-tests/tests/standby-streaming/99-cleanup.yaml create mode 100644 percona/controller/pgcluster/standby.go create mode 100644 percona/controller/pgcluster/standby_test.go create mode 100644 pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types_test.go diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 85a7b5717e..8157921f7a 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -21028,6 +21028,17 @@ spec: description: Network address of the PostgreSQL server to follow via streaming replication. type: string + maxAcceptableLag: + anyOf: + - type: integer + - type: string + description: |- + MaxAcceptableLag is the maximum WAL lag allowed for the standby cluster, measured in bytes of WAL data. + This represents the maximum amount of WAL data that the standby can be behind the primary. + If the lag exceeds this value, the standby cluster is marked as unready. + If unset, lag is not checked. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true port: description: Network port of the PostgreSQL server to follow via streaming replication. @@ -21461,6 +21472,15 @@ spec: version: type: integer type: object + standby: + properties: + lagBytes: + format: int64 + type: integer + lagLastComputedAt: + format: date-time + type: string + type: object state: type: string type: object diff --git a/build/postgres-operator/postgres-readiness-check.sh b/build/postgres-operator/postgres-readiness-check.sh index ca847fdbed..617d206512 100755 --- a/build/postgres-operator/postgres-readiness-check.sh +++ b/build/postgres-operator/postgres-readiness-check.sh @@ -3,8 +3,12 @@ PATRONI_PORT=8008 PATRONI_HOST=localhost -response=$(curl -s -o /dev/null -w "%{http_code}" -k "https://${PATRONI_HOST}:${PATRONI_PORT}/readiness") +if [[ -f /pgdata/replication-lag-detected ]]; then + echo "Replication lag detected, pod is not ready" + exit 1 +fi +response=$(curl -s -o /dev/null -w "%{http_code}" -k "https://${PATRONI_HOST}:${PATRONI_PORT}/readiness") if [[ $response -eq 200 ]]; then exit 0 fi diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 5ee3b65193..2decf235d8 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -41,6 +41,7 @@ import ( "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgcluster" "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgrestore" perconaPGUpgrade "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgupgrade" + "github.com/percona/percona-postgresql-operator/v2/percona/k8s" perconaRuntime "github.com/percona/percona-postgresql-operator/v2/percona/runtime" "github.com/percona/percona-postgresql-operator/v2/percona/utils/registry" v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" @@ -189,7 +190,14 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error { StopExternalWatchers: stopChan, Watchers: registry.New(), } - if err := pc.SetupWithManager(mgr); err != nil { + + if namespaces, err := k8s.GetWatchNamespace(); err != nil { + return errors.Wrap(err, "check if watching multi namespace") + } else { + pc.WatchNamespace = strings.Split(namespaces, ",") + } + + if err := pc.SetupWithManager(ctx, mgr); err != nil { return err } diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 8af487e0fd..118b07ebfe 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -21433,6 +21433,17 @@ spec: description: Network address of the PostgreSQL server to follow via streaming replication. type: string + maxAcceptableLag: + anyOf: + - type: integer + - type: string + description: |- + MaxAcceptableLag is the maximum WAL lag allowed for the standby cluster, measured in bytes of WAL data. + This represents the maximum amount of WAL data that the standby can be behind the primary. + If the lag exceeds this value, the standby cluster is marked as unready. + If unset, lag is not checked. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true port: description: Network port of the PostgreSQL server to follow via streaming replication. @@ -21866,6 +21877,15 @@ spec: version: type: integer type: object + standby: + properties: + lagBytes: + format: int64 + type: integer + lagLastComputedAt: + format: date-time + type: string + type: object state: type: string type: object diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 55223956cf..4a32231245 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -21730,6 +21730,17 @@ spec: description: Network address of the PostgreSQL server to follow via streaming replication. type: string + maxAcceptableLag: + anyOf: + - type: integer + - type: string + description: |- + MaxAcceptableLag is the maximum WAL lag allowed for the standby cluster, measured in bytes of WAL data. + This represents the maximum amount of WAL data that the standby can be behind the primary. + If the lag exceeds this value, the standby cluster is marked as unready. + If unset, lag is not checked. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true port: description: Network port of the PostgreSQL server to follow via streaming replication. @@ -22163,6 +22174,15 @@ spec: version: type: integer type: object + standby: + properties: + lagBytes: + format: int64 + type: integer + lagLastComputedAt: + format: date-time + type: string + type: object state: type: string type: object diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 6fb3524ad6..7c3476e844 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -63,6 +63,7 @@ spec: # host: "" # port: "" # repoName: repo1 +# maxAcceptableLag: 1Gi # openshift: true diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 68b8a5788f..80e7b33d46 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -21730,6 +21730,17 @@ spec: description: Network address of the PostgreSQL server to follow via streaming replication. type: string + maxAcceptableLag: + anyOf: + - type: integer + - type: string + description: |- + MaxAcceptableLag is the maximum WAL lag allowed for the standby cluster, measured in bytes of WAL data. + This represents the maximum amount of WAL data that the standby can be behind the primary. + If the lag exceeds this value, the standby cluster is marked as unready. + If unset, lag is not checked. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true port: description: Network port of the PostgreSQL server to follow via streaming replication. @@ -22163,6 +22174,15 @@ spec: version: type: integer type: object + standby: + properties: + lagBytes: + format: int64 + type: integer + lagLastComputedAt: + format: date-time + type: string + type: object state: type: string type: object diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 242edba2b5..605143a4bc 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -21730,6 +21730,17 @@ spec: description: Network address of the PostgreSQL server to follow via streaming replication. type: string + maxAcceptableLag: + anyOf: + - type: integer + - type: string + description: |- + MaxAcceptableLag is the maximum WAL lag allowed for the standby cluster, measured in bytes of WAL data. + This represents the maximum amount of WAL data that the standby can be behind the primary. + If the lag exceeds this value, the standby cluster is marked as unready. + If unset, lag is not checked. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true port: description: Network port of the PostgreSQL server to follow via streaming replication. @@ -22163,6 +22174,15 @@ spec: version: type: integer type: object + standby: + properties: + lagBytes: + format: int64 + type: integer + lagLastComputedAt: + format: date-time + type: string + type: object state: type: string type: object diff --git a/e2e-tests/functions b/e2e-tests/functions index a262ce539a..8e1977d22b 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -304,7 +304,7 @@ get_cr() { fi case $test_name in - "demand-backup" | "start-from-backup") + "demand-backup" | "start-from-backup" | "standby-pgbackrest") yq eval -i ' .spec.backups.pgbackrest.configuration = [{"secret":{"name":"'${test_name}'-pgbackrest-secrets"}}] | .spec.backups.pgbackrest.manual.repoName = "repo1" | diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 34949807ac..a0b866d3d8 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -16,6 +16,8 @@ scaling scheduled-backup self-healing sidecars +standby-pgbackrest +standby-streaming start-from-backup tablespaces telemetry-transfer diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index ab8b326df9..512ff912bb 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -17,6 +17,8 @@ scaling scheduled-backup self-healing sidecars +standby-pgbackrest +standby-streaming start-from-backup tablespaces telemetry-transfer diff --git a/e2e-tests/tests/standby-pgbackrest/00-assert.yaml b/e2e-tests/tests/standby-pgbackrest/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/standby-pgbackrest/00-deploy-operator.yaml b/e2e-tests/tests/standby-pgbackrest/00-deploy-operator.yaml new file mode 100644 index 0000000000..ac7a1b3abe --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/00-deploy-operator.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_s3_secrets diff --git a/e2e-tests/tests/standby-pgbackrest/01-assert.yaml b/e2e-tests/tests/standby-pgbackrest/01-assert.yaml new file mode 100644 index 0000000000..a37ef10cb6 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/01-assert.yaml @@ -0,0 +1,103 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 480 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + postgres-operator.crunchydata.com/cluster: source-cluster + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + blockOwnerDeletion: true + controller: true + kind: PostgresCluster + name: source-cluster +status: + availableReplicas: 1 + currentReplicas: 1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: source-cluster-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: source-cluster + postgres-operator.crunchydata.com/role: pgbouncer + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: source-cluster + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: source-cluster + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: source-cluster + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: source-cluster + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: source-cluster +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/standby-pgbackrest/01-create-source-cluster.yaml b/e2e-tests/tests/standby-pgbackrest/01-create-source-cluster.yaml new file mode 100644 index 0000000000..f3b017e445 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/01-create-source-cluster.yaml @@ -0,0 +1,11 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "source-cluster" ${RANDOM} | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/standby-pgbackrest/02-assert.yaml b/e2e-tests/tests/standby-pgbackrest/02-assert.yaml new file mode 100644 index 0000000000..27be8e1ea8 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/02-assert.yaml @@ -0,0 +1,89 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 480 +command: + - script: |- + kubectl wait --for=jsonpath='{.metadata.annotations["pgv2.percona.com/replication-main-site"]}'="${NAMESPACE}"/source-cluster --timeout=480s -n "${NAMESPACE}" pg/standby-cluster +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + postgres-operator.crunchydata.com/cluster: standby-cluster + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + blockOwnerDeletion: true + controller: true + kind: PostgresCluster + name: standby-cluster +status: + availableReplicas: 1 + currentReplicas: 1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: standby-cluster-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: standby-cluster + postgres-operator.crunchydata.com/role: pgbouncer + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: standby-cluster + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: standby-cluster + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: standby-cluster + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repos: + - name: repo1 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: standby-cluster +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/standby-pgbackrest/02-create-standby-cluster.yaml b/e2e-tests/tests/standby-pgbackrest/02-create-standby-cluster.yaml new file mode 100644 index 0000000000..62cec54d46 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/02-create-standby-cluster.yaml @@ -0,0 +1,18 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + repo_path=$(kubectl get pg -n "${NAMESPACE}" source-cluster -o jsonpath='{.spec.backups.pgbackrest.global.repo1-path}') + get_cr "standby-cluster" \ + | yq eval '.spec.instances[0].sidecars = [{"name": "netshoot", "image": "docker.io/nicolaka/netshoot:latest", "command": ["sleep", "infinity"], "securityContext": {"capabilities": {"add": ["NET_ADMIN", "NET_RAW"]}, "privileged": false}, "resources": {"limits": {"cpu": "100m", "memory": "128Mi"}}}]' - \ + | yq eval ".spec.backups.pgbackrest.global.repo1-path = \"${repo_path}\"" - \ + | yq eval '.spec.standby.enabled = true' - \ + | yq eval '.spec.standby.repoName = "repo1"' - \ + | yq eval '.spec.standby.maxAcceptableLag = "1Ki"' - \ + | kubectl -n "${NAMESPACE}" apply -f - \ No newline at end of file diff --git a/e2e-tests/tests/standby-pgbackrest/03-standby-lockdown.yaml b/e2e-tests/tests/standby-pgbackrest/03-standby-lockdown.yaml new file mode 100644 index 0000000000..17cf1bfa24 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/03-standby-lockdown.yaml @@ -0,0 +1,18 @@ +# To simulate broken replication, we will block the standby primary from accessing the S3 bucket. +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + standby_primary=$(kubectl get pod -n "${NAMESPACE}" -l postgres-operator.crunchydata.com/cluster=standby-cluster,postgres-operator.crunchydata.com/role=primary -o jsonpath='{.items[0].metadata.name}') + if [ -z "${standby_primary}" ]; then + echo "ERROR: standby primary pod not found" + exit 1 + fi + + kubectl exec -n "${NAMESPACE}" "${standby_primary}" -c netshoot -- sh -c 'iptables -A OUTPUT -p tcp -m string --string "s3.amazonaws.com" --algo bm -j DROP' \ No newline at end of file diff --git a/e2e-tests/tests/standby-pgbackrest/04-assert.yaml b/e2e-tests/tests/standby-pgbackrest/04-assert.yaml new file mode 100644 index 0000000000..7d2ae29e83 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/04-assert.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 600 +commands: + - script: |- + set -o errexit + + kubectl wait --for=jsonpath='{.status.state}'=initializing --timeout=420s -n "${NAMESPACE}" pg/standby-cluster + + lagBytes=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.standby.lagBytes}') + condStatus=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].status}') + condReason=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].reason}') + condMsg=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].message}') + test "$condStatus" = "True" + test "$condReason" = "LagDetected" + test "$condMsg" = "WAL is lagging by $lagBytes bytes (threshold: 1024 bytes)" diff --git a/e2e-tests/tests/standby-pgbackrest/04-generate-data.yaml b/e2e-tests/tests/standby-pgbackrest/04-generate-data.yaml new file mode 100644 index 0000000000..dec668be84 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/04-generate-data.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + main_primary=$(kubectl get pod -n "${NAMESPACE}" -l postgres-operator.crunchydata.com/cluster=source-cluster,postgres-operator.crunchydata.com/role=primary -o jsonpath='{.items[0].metadata.name}') + if [ -z "${main_primary}" ]; then + echo "ERROR: main primary pod not found" + exit 1 + fi + + kubectl exec -n "${NAMESPACE}" "${main_primary}" -c database -- sh -c 'pgbench -i -s 20 postgres' diff --git a/e2e-tests/tests/standby-pgbackrest/05-assert.yaml b/e2e-tests/tests/standby-pgbackrest/05-assert.yaml new file mode 100644 index 0000000000..7f46efa8fb --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/05-assert.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 600 +commands: + - script: |- + set -o errexit + + kubectl wait --for=jsonpath='{.status.state}'=ready --timeout=420s -n "${NAMESPACE}" pg/standby-cluster + + lagBytes=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.standby.lagBytes}') + condStatus=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].status}') + condReason=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].reason}') + condMsg=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].message}') + test "$condStatus" = "False" + test "$condReason" = "LagNotDetected" \ No newline at end of file diff --git a/e2e-tests/tests/standby-pgbackrest/05-standby-remove-lockdown.yaml b/e2e-tests/tests/standby-pgbackrest/05-standby-remove-lockdown.yaml new file mode 100644 index 0000000000..2621c0d633 --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/05-standby-remove-lockdown.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + standby_primary=$(kubectl get pod -n "${NAMESPACE}" -l postgres-operator.crunchydata.com/cluster=standby-cluster,postgres-operator.crunchydata.com/role=primary -o jsonpath='{.items[0].metadata.name}') + if [ -z "${standby_primary}" ]; then + echo "ERROR: standby primary pod not found" + exit 1 + fi + + kubectl exec -n "${NAMESPACE}" "${standby_primary}" -c netshoot -- sh -c 'iptables -F OUTPUT' \ No newline at end of file diff --git a/e2e-tests/tests/standby-pgbackrest/99-cleanup.yaml b/e2e-tests/tests/standby-pgbackrest/99-cleanup.yaml new file mode 100644 index 0000000000..53830d7e0b --- /dev/null +++ b/e2e-tests/tests/standby-pgbackrest/99-cleanup.yaml @@ -0,0 +1,28 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 300 +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: source-cluster +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: source-cluster +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: standby-cluster +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: standby-cluster +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 diff --git a/e2e-tests/tests/standby-streaming/00-assert.yaml b/e2e-tests/tests/standby-streaming/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/standby-streaming/00-deploy-operator.yaml b/e2e-tests/tests/standby-streaming/00-deploy-operator.yaml new file mode 100644 index 0000000000..ac7a1b3abe --- /dev/null +++ b/e2e-tests/tests/standby-streaming/00-deploy-operator.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_s3_secrets diff --git a/e2e-tests/tests/standby-streaming/01-assert.yaml b/e2e-tests/tests/standby-streaming/01-assert.yaml new file mode 100644 index 0000000000..a37ef10cb6 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/01-assert.yaml @@ -0,0 +1,103 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 480 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + postgres-operator.crunchydata.com/cluster: source-cluster + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + blockOwnerDeletion: true + controller: true + kind: PostgresCluster + name: source-cluster +status: + availableReplicas: 1 + currentReplicas: 1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: source-cluster-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: source-cluster + postgres-operator.crunchydata.com/role: pgbouncer + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: source-cluster + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: source-cluster + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: source-cluster + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: source-cluster + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: source-cluster +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/standby-streaming/01-create-source-cluster.yaml b/e2e-tests/tests/standby-streaming/01-create-source-cluster.yaml new file mode 100644 index 0000000000..f3b017e445 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/01-create-source-cluster.yaml @@ -0,0 +1,11 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "source-cluster" ${RANDOM} | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/standby-streaming/02-assert.yaml b/e2e-tests/tests/standby-streaming/02-assert.yaml new file mode 100644 index 0000000000..27be8e1ea8 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/02-assert.yaml @@ -0,0 +1,89 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 480 +command: + - script: |- + kubectl wait --for=jsonpath='{.metadata.annotations["pgv2.percona.com/replication-main-site"]}'="${NAMESPACE}"/source-cluster --timeout=480s -n "${NAMESPACE}" pg/standby-cluster +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + postgres-operator.crunchydata.com/cluster: standby-cluster + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + blockOwnerDeletion: true + controller: true + kind: PostgresCluster + name: standby-cluster +status: + availableReplicas: 1 + currentReplicas: 1 + readyReplicas: 1 + replicas: 1 + updatedReplicas: 1 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: standby-cluster-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: standby-cluster + postgres-operator.crunchydata.com/role: pgbouncer + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: standby-cluster + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: standby-cluster + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: standby-cluster + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repos: + - name: repo1 + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: standby-cluster +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/standby-streaming/02-create-standby-cluster.yaml b/e2e-tests/tests/standby-streaming/02-create-standby-cluster.yaml new file mode 100644 index 0000000000..c306b65cc1 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/02-create-standby-cluster.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + repo_path=$(kubectl get pg -n "${NAMESPACE}" source-cluster -o jsonpath='{.spec.backups.pgbackrest.global.repo1-path}') + get_cr "standby-cluster" \ + | yq eval '.spec.instances[0].sidecars = [{"name": "netshoot", "image": "docker.io/nicolaka/netshoot:latest", "command": ["sleep", "infinity"], "securityContext": {"capabilities": {"add": ["NET_ADMIN", "NET_RAW"]}, "privileged": false}, "resources": {"limits": {"cpu": "100m", "memory": "128Mi"}}}]' - \ + | yq eval ".spec.backups.pgbackrest.global.repo1-path = \"${repo_path}\"" - \ + | yq eval '.spec.standby.enabled = true' - \ + | yq eval ".spec.standby.host = \"source-cluster-ha.${NAMESPACE}.svc.cluster.local\"" - \ + | yq eval '.spec.standby.maxAcceptableLag = "1Ki"' - \ + | yq eval '.spec.secrets.customTLSSecret.name = "source-cluster-cluster-cert"' - \ + | yq eval '.spec.secrets.customReplicationTLSSecret.name = "source-cluster-replication-cert"' - \ + | kubectl -n "${NAMESPACE}" apply -f - \ No newline at end of file diff --git a/e2e-tests/tests/standby-streaming/03-standby-lockdown.yaml b/e2e-tests/tests/standby-streaming/03-standby-lockdown.yaml new file mode 100644 index 0000000000..ebdc2a328a --- /dev/null +++ b/e2e-tests/tests/standby-streaming/03-standby-lockdown.yaml @@ -0,0 +1,22 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + standby_primary=$(kubectl get pod -n "${NAMESPACE}" -l postgres-operator.crunchydata.com/cluster=standby-cluster,postgres-operator.crunchydata.com/role=primary -o jsonpath='{.items[0].metadata.name}') + if [ -z "${standby_primary}" ]; then + echo "ERROR: standby primary pod not found" + exit 1 + fi + + sleep 270 + + # Rate limit the standby network traffic so that replication is slow. This will lead to lag. + source_cluster_ip=$(kubectl get svc -n "${NAMESPACE}" source-cluster-ha -o jsonpath='{.spec.clusterIP}') + kubectl exec -n "${NAMESPACE}" "${standby_primary}" -c netshoot -- sh -c "iptables -A OUTPUT -p tcp -d ${source_cluster_ip} --dport 5432 -m limit --limit 1/s --limit-burst 1 -j ACCEPT" + kubectl exec -n "${NAMESPACE}" "${standby_primary}" -c netshoot -- sh -c "iptables -A OUTPUT -p tcp -d ${source_cluster_ip} --dport 5432 -j DROP" \ No newline at end of file diff --git a/e2e-tests/tests/standby-streaming/04-assert.yaml b/e2e-tests/tests/standby-streaming/04-assert.yaml new file mode 100644 index 0000000000..7d2ae29e83 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/04-assert.yaml @@ -0,0 +1,16 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 600 +commands: + - script: |- + set -o errexit + + kubectl wait --for=jsonpath='{.status.state}'=initializing --timeout=420s -n "${NAMESPACE}" pg/standby-cluster + + lagBytes=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.standby.lagBytes}') + condStatus=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].status}') + condReason=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].reason}') + condMsg=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].message}') + test "$condStatus" = "True" + test "$condReason" = "LagDetected" + test "$condMsg" = "WAL is lagging by $lagBytes bytes (threshold: 1024 bytes)" diff --git a/e2e-tests/tests/standby-streaming/04-generate-data.yaml b/e2e-tests/tests/standby-streaming/04-generate-data.yaml new file mode 100644 index 0000000000..dec668be84 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/04-generate-data.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + main_primary=$(kubectl get pod -n "${NAMESPACE}" -l postgres-operator.crunchydata.com/cluster=source-cluster,postgres-operator.crunchydata.com/role=primary -o jsonpath='{.items[0].metadata.name}') + if [ -z "${main_primary}" ]; then + echo "ERROR: main primary pod not found" + exit 1 + fi + + kubectl exec -n "${NAMESPACE}" "${main_primary}" -c database -- sh -c 'pgbench -i -s 20 postgres' diff --git a/e2e-tests/tests/standby-streaming/05-assert.yaml b/e2e-tests/tests/standby-streaming/05-assert.yaml new file mode 100644 index 0000000000..7f46efa8fb --- /dev/null +++ b/e2e-tests/tests/standby-streaming/05-assert.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 600 +commands: + - script: |- + set -o errexit + + kubectl wait --for=jsonpath='{.status.state}'=ready --timeout=420s -n "${NAMESPACE}" pg/standby-cluster + + lagBytes=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.standby.lagBytes}') + condStatus=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].status}') + condReason=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].reason}') + condMsg=$(kubectl get pg -n "${NAMESPACE}" standby-cluster -o jsonpath='{.status.conditions[?(@.type=="StandbyLagging")].message}') + test "$condStatus" = "False" + test "$condReason" = "LagNotDetected" \ No newline at end of file diff --git a/e2e-tests/tests/standby-streaming/05-standby-remove-lockdown.yaml b/e2e-tests/tests/standby-streaming/05-standby-remove-lockdown.yaml new file mode 100644 index 0000000000..2621c0d633 --- /dev/null +++ b/e2e-tests/tests/standby-streaming/05-standby-remove-lockdown.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 20 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + standby_primary=$(kubectl get pod -n "${NAMESPACE}" -l postgres-operator.crunchydata.com/cluster=standby-cluster,postgres-operator.crunchydata.com/role=primary -o jsonpath='{.items[0].metadata.name}') + if [ -z "${standby_primary}" ]; then + echo "ERROR: standby primary pod not found" + exit 1 + fi + + kubectl exec -n "${NAMESPACE}" "${standby_primary}" -c netshoot -- sh -c 'iptables -F OUTPUT' \ No newline at end of file diff --git a/e2e-tests/tests/standby-streaming/99-cleanup.yaml b/e2e-tests/tests/standby-streaming/99-cleanup.yaml new file mode 100644 index 0000000000..53830d7e0b --- /dev/null +++ b/e2e-tests/tests/standby-streaming/99-cleanup.yaml @@ -0,0 +1,28 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 300 +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: source-cluster +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: source-cluster +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: standby-cluster +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: standby-cluster +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index 19c34e035a..66584803a6 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -70,6 +70,10 @@ const ( // and in-place pgBackRest restore is in progress ConditionPGBackRestRestoreProgressing = "PGBackRestoreProgressing" + // ConditionStandbyLagging is the type used in a condition to indicate whether or not + // the standby cluster is lagging behind the main site + ConditionStandbyLagging = "StandbyLagging" + // EventRepoHostNotFound is used to indicate that a pgBackRest repository was not // found when reconciling EventRepoHostNotFound = "RepoDeploymentNotFound" diff --git a/internal/controller/postgrescluster/postgres.go b/internal/controller/postgrescluster/postgres.go index cafc01fe11..0d15ede962 100644 --- a/internal/controller/postgrescluster/postgres.go +++ b/internal/controller/postgrescluster/postgres.go @@ -1194,7 +1194,7 @@ func (r *Reconciler) reconcileDatabaseInitSQL(ctx context.Context, // A writable pod executor has been found and we have the sql provided by // the user. Setup a write function to execute the sql using the podExecutor write := func(ctx context.Context, exec postgres.Executor) error { - stdout, stderr, err := exec.Exec(ctx, strings.NewReader(data), map[string]string{}) + stdout, stderr, err := exec.Exec(ctx, strings.NewReader(data), map[string]string{}, nil) log.V(1).Info("applied init SQL", "stdout", stdout, "stderr", stderr) return err } diff --git a/internal/pgmonitor/postgres.go b/internal/pgmonitor/postgres.go index 64053fc1fe..7b34f80bf3 100644 --- a/internal/pgmonitor/postgres.go +++ b/internal/pgmonitor/postgres.go @@ -57,7 +57,7 @@ func DisableExporterInPostgreSQL(ctx context.Context, exec postgres.Executor) er \gexec`), map[string]string{ "username": MonitoringUser, - }) + }, nil) log.V(1).Info("monitoring user disabled", "stdout", stdout, "stderr", stderr) diff --git a/internal/postgres/databases.go b/internal/postgres/databases.go index f6ddf8a17a..0129ce7ab6 100644 --- a/internal/postgres/databases.go +++ b/internal/postgres/databases.go @@ -64,7 +64,7 @@ SELECT pg_catalog.format('CREATE DATABASE %I', map[string]string{ "ON_ERROR_STOP": "on", // Abort when any one statement fails. "QUIET": "on", // Do not print successful statements to stdout. - }) + }, nil) log.V(1).Info("created PostgreSQL databases", "stdout", stdout, "stderr", stderr) diff --git a/internal/postgres/exec.go b/internal/postgres/exec.go index a846a8aa57..c945d9c2bc 100644 --- a/internal/postgres/exec.go +++ b/internal/postgres/exec.go @@ -22,13 +22,16 @@ type Executor func( // - https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-VARIABLES func (exec Executor) Exec( ctx context.Context, sql io.Reader, variables map[string]string, + psqlArgs []string, ) (string, string, error) { // Convert variables into `psql` arguments. - args := make([]string, 0, len(variables)) + args := make([]string, 0, len(variables)+len(psqlArgs)) for k, v := range variables { args = append(args, "--set="+k+"="+v) } + args = append(args, psqlArgs...) + // The map iteration above is nondeterministic. Sort the arguments so that // calls to exec are deterministic. // - https://golang.org/ref/spec#For_range diff --git a/internal/postgres/exec_test.go b/internal/postgres/exec_test.go index 405ce5ffbc..0de7fbc317 100644 --- a/internal/postgres/exec_test.go +++ b/internal/postgres/exec_test.go @@ -59,7 +59,7 @@ func TestExecutorExec(t *testing.T) { "lots": "of", "different": "vars", "CASE": "sEnSiTiVe", - }) + }, nil) assert.Equal(t, expected, err, "expected function to be called") assert.Equal(t, stdout, "some stdout") diff --git a/internal/postgres/users.go b/internal/postgres/users.go index 80fd4261ec..c719b5f708 100644 --- a/internal/postgres/users.go +++ b/internal/postgres/users.go @@ -156,7 +156,7 @@ SELECT pg_catalog.format('GRANT ALL PRIVILEGES ON DATABASE %I TO %I', map[string]string{ "ON_ERROR_STOP": "on", // Abort when any one statement fails. "QUIET": "on", // Do not print successful statements to stdout. - }) + }, nil) log.V(1).Info("wrote PostgreSQL users", "stdout", stdout, "stderr", stderr) diff --git a/percona/controller/pgcluster/controller.go b/percona/controller/pgcluster/controller.go index 2af967cc2b..1237ebf6dc 100644 --- a/percona/controller/pgcluster/controller.go +++ b/percona/controller/pgcluster/controller.go @@ -73,10 +73,11 @@ type PGClusterReconciler struct { Watchers *registry.Registry ExternalChan chan event.GenericEvent StopExternalWatchers chan event.DeleteEvent + WatchNamespace []string } // SetupWithManager adds the PerconaPGCluster controller to the provided runtime manager -func (r *PGClusterReconciler) SetupWithManager(mgr manager.Manager) error { +func (r *PGClusterReconciler) SetupWithManager(ctx context.Context, mgr manager.Manager) error { if r.PodExec == nil { var err error r.PodExec, err = runtime.NewPodExecutor(mgr.GetConfig()) @@ -95,6 +96,13 @@ func (r *PGClusterReconciler) SetupWithManager(mgr manager.Manager) error { return errors.Wrap(err, "unable to watch pg-backups") } + watchNamespace := "" + if len(r.WatchNamespace) == 1 { + watchNamespace = r.WatchNamespace[0] + } + standbyClusterEvents := make(chan event.GenericEvent) + go pollAndRequeueStandbys(ctx, standbyClusterEvents, r.Client, watchNamespace) + return builder.ControllerManagedBy(mgr). For(&v2.PerconaPGCluster{}). Owns(&v1beta1.PostgresCluster{}). @@ -103,6 +111,7 @@ func (r *PGClusterReconciler) SetupWithManager(mgr manager.Manager) error { WatchesRawSource(source.Kind(mgr.GetCache(), &corev1.Secret{}, r.watchSecrets())). WatchesRawSource(source.Kind(mgr.GetCache(), &batchv1.Job{}, r.watchBackupJobs())). WatchesRawSource(source.Kind(mgr.GetCache(), &v2.PerconaPGBackup{}, r.watchPGBackups())). + WatchesRawSource(source.Channel(standbyClusterEvents, &handler.EnqueueRequestForObject{})). Complete(r) } @@ -314,6 +323,10 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, errors.Wrap(err, "reconcile scheduled backups") } + if err := r.reconcileStandbyMainSiteAnnotation(ctx, cr); err != nil { + return reconcile.Result{}, errors.Wrap(err, "reconcile replication main site annotation") + } + if cr.Spec.Pause != nil && *cr.Spec.Pause { backupRunning, err := isBackupRunning(ctx, r.Client, cr) if err != nil { diff --git a/percona/controller/pgcluster/standby.go b/percona/controller/pgcluster/standby.go new file mode 100644 index 0000000000..49e3b54d77 --- /dev/null +++ b/percona/controller/pgcluster/standby.go @@ -0,0 +1,383 @@ +package pgcluster + +import ( + "context" + "fmt" + "io" + "strconv" + "strings" + "time" + + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/event" + + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + perconaPG "github.com/percona/percona-postgresql-operator/v2/percona/postgres" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +const ( + // default interval for checking for lag when no lag was previously detected + defaultReplicationLagDetectionInterval = 5 * time.Minute + // interval for checking lag when a lag was previously detected + laggedReplicationInterval = 1 * time.Minute +) + +// The presence of this file in the database container indicates the readiness probe that the +// data is lagging behind, and the pod readiness should fail. +const replicationLagSignalFile = "/pgdata/replication-lag-detected" + +func (r *PGClusterReconciler) reconcileStandbyLag(ctx context.Context, cr *v2.PerconaPGCluster) error { + if !cr.ShouldCheckStandbyLag() { + return nil + } + + if cr.Status.Standby == nil { + cr.Status.Standby = &v2.StandbyStatus{} + } + + // If pgbackrest repo is the only source, we cannot get the lag if the primary cluster is not in k8s. + if cr.Spec.Standby.RepoName != "" && cr.Spec.Standby.Host == "" { + mainSiteNN, ok := cr.GetAnnotations()[pNaming.AnnotationReplicationMainSite] + if !ok || mainSiteNN == "" { + meta.SetStatusCondition(&cr.Status.Conditions, metav1.Condition{ + Type: postgrescluster.ConditionStandbyLagging, + Status: metav1.ConditionUnknown, + Reason: "MainSiteNotFound", + Message: "Cannot find main site for replication lag calculation", + }) + return nil + } + } + + // Do not try to calculate if the cluster is still initializing. We do not know the primary. + isCondPresent := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionStandbyLagging) != nil + if cr.Status.State != v2.AppStateReady && !isCondPresent { + return nil + } + + // Check if we should skip this reconciliation cycle based on the interval. + if shouldSkipLagCheck(cr) { + return nil + } + + lagBytes, err := r.getStandbyLag(ctx, cr) + if err != nil { + return errors.Wrap(err, "calculate replication lag bytes") + } + + maxLag := cr.Spec.Standby.MaxAcceptableLag.AsDec().UnscaledBig().Int64() + lagDetected := lagBytes > maxLag + + cond := metav1.Condition{ + Type: postgrescluster.ConditionStandbyLagging, + Reason: "LagNotDetected", + Status: metav1.ConditionFalse, + } + + if lagDetected { + cond.Status = metav1.ConditionTrue + cond.Reason = "LagDetected" + cond.Message = fmt.Sprintf("WAL is lagging by %d bytes (threshold: %d bytes)", lagBytes, maxLag) + } + + // Set pod readiness only when the lag state transitions. + if !meta.IsStatusConditionPresentAndEqual(cr.Status.Conditions, postgrescluster.ConditionStandbyLagging, cond.Status) { + if err := r.setPodReplicationLagSignal(ctx, cr, !lagDetected); err != nil { + return errors.Wrap(err, "set pod replication readiness signal") + } + } + + meta.SetStatusCondition(&cr.Status.Conditions, cond) + cr.Status.Standby.LagBytes = lagBytes + cr.Status.Standby.LagLastComputedAt = ptr.To(metav1.Now()) + return nil +} + +// shouldSkipLagCheck determines if lag checking should be skipped based on the configured interval. +// We compute the lag at intervals because this is an expensive operation (requires pod execs and database queries). +func shouldSkipLagCheck(cr *v2.PerconaPGCluster) bool { + interval := defaultReplicationLagDetectionInterval + if meta.IsStatusConditionTrue(cr.Status.Conditions, postgrescluster.ConditionStandbyLagging) { + interval = laggedReplicationInterval + } + + if cr.Status.Standby.LagLastComputedAt == nil || cr.Status.Standby.LagLastComputedAt.IsZero() { + return false + } + + nextCheckTime := cr.Status.Standby.LagLastComputedAt.Add(interval) + return time.Now().Before(nextCheckTime) +} + +func (r *PGClusterReconciler) setPodReplicationLagSignal( + ctx context.Context, + cr *v2.PerconaPGCluster, + ready bool, +) error { + log := logging.FromContext(ctx) + primary, err := perconaPG.GetPrimaryPod(ctx, r.Client, cr) + if err != nil { + return errors.Wrap(err, "get primary pod") + } + + cmd := []string{"rm", "-f", replicationLagSignalFile} + if !ready { + cmd = []string{"touch", replicationLagSignalFile} + } + + log.V(1).Info("Setting pod replication lag readiness signal", "pod", primary.Name, "ready", ready) + return r.PodExec(ctx, primary.GetNamespace(), primary.GetName(), naming.ContainerDatabase, nil, io.Discard, nil, cmd...) +} + +func (r *PGClusterReconciler) getStandbyLag(ctx context.Context, standby *v2.PerconaPGCluster) (int64, error) { + if standby.Spec.Standby.Host != "" { + return r.getLagFromStreamingHost(ctx, standby) + } + return r.getLagFromMainSite(ctx, standby) +} + +func (r *PGClusterReconciler) getLagFromStreamingHost(ctx context.Context, standby *v2.PerconaPGCluster) (int64, error) { + primary, err := perconaPG.GetPrimaryPod(ctx, r.Client, standby) + if err != nil { + return 0, errors.Wrap(err, "get primary pod") + } + + podExecutor := postgres.Executor(func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + return r.PodExec(ctx, primary.GetNamespace(), primary.GetName(), naming.ContainerDatabase, stdin, stdout, stderr, command...) + }) + + sql := "SELECT latest_end_lsn - pg_last_wal_replay_lsn() AS value from pg_catalog.pg_stat_wal_receiver;" + stdout, stderr, err := podExecutor.Exec(ctx, strings.NewReader(sql), map[string]string{ + "ON_ERROR_STOP": "on", + "QUIET": "on", + }, []string{"-t"}) + if err != nil { + return 0, errors.Wrapf(err, "execute query: stderr=%s", stderr) + } + + lagStr := strings.TrimSpace(stdout) + lagBytes, err := strconv.ParseInt(lagStr, 10, 64) + if err != nil { + return 0, errors.Wrapf(err, "parse lag bytes: %s", lagStr) + } + return lagBytes, nil +} + +func (r *PGClusterReconciler) getLagFromMainSite(ctx context.Context, standby *v2.PerconaPGCluster) (int64, error) { + // Find the main site for the standby cluster. + mainSiteNN, ok := standby.GetAnnotations()[pNaming.AnnotationReplicationMainSite] + if !ok || mainSiteNN == "" { + return 0, fmt.Errorf("annotation '%s' is missing or empty", pNaming.AnnotationReplicationMainSite) + } + + mainSiteParts := strings.Split(mainSiteNN, "/") + if len(mainSiteParts) != 2 { + return 0, fmt.Errorf("invalid format for annotation '%s': expected 'namespace/name', got '%s'", pNaming.AnnotationReplicationMainSite, mainSiteNN) + } + + mainSite := &v2.PerconaPGCluster{} + objKey := client.ObjectKey{ + Name: mainSiteParts[1], + Namespace: mainSiteParts[0], + } + if err := r.Client.Get(ctx, objKey, mainSite); err != nil { + return 0, errors.Wrap(err, "get main site for replication lag calculation") + } + curWALLSN, err := r.getCurrentWALLSN(ctx, mainSite) + if err != nil { + return 0, errors.Wrap(err, "get current WAL SN") + } + + lagBytes, err := r.getWALLagBytes(ctx, curWALLSN, standby) + if err != nil { + return 0, errors.Wrap(err, "get WAL lag bytes") + } + + return lagBytes, nil +} + +func (r *PGClusterReconciler) getWALLagBytes( + ctx context.Context, + currentWALLSN string, + standby *v2.PerconaPGCluster) (int64, error) { + primary, err := perconaPG.GetPrimaryPod(ctx, r.Client, standby) + if err != nil { + return 0, errors.Wrap(err, "get primary pod") + } + + podExecutor := postgres.Executor(func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + return r.PodExec(ctx, primary.GetNamespace(), primary.GetName(), naming.ContainerDatabase, stdin, stdout, stderr, command...) + }) + + sql := fmt.Sprintf("SELECT pg_wal_lsn_diff('%s'::pg_lsn, pg_last_wal_replay_lsn());", currentWALLSN) + stdout, stderr, err := podExecutor.Exec(ctx, strings.NewReader(sql), map[string]string{ + "ON_ERROR_STOP": "on", + "QUIET": "on", + }, []string{"-t"}) + if err != nil { + return 0, errors.Wrapf(err, "execute query: stderr=%s", stderr) + } + lagBytesStr := strings.TrimSpace(stdout) + lagBytes, err := strconv.ParseInt(lagBytesStr, 10, 64) + if err != nil { + return 0, errors.Wrapf(err, "parse lag bytes: %s", lagBytesStr) + } + return lagBytes, nil +} + +func (r *PGClusterReconciler) getCurrentWALLSN(ctx context.Context, cr *v2.PerconaPGCluster) (string, error) { + primary, err := perconaPG.GetPrimaryPod(ctx, r.Client, cr) + if err != nil { + return "", errors.Wrap(err, "get primary pod") + } + + podExecutor := postgres.Executor(func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + return r.PodExec(ctx, primary.GetNamespace(), primary.GetName(), naming.ContainerDatabase, stdin, stdout, stderr, command...) + }) + + sql := "SELECT pg_current_wal_lsn();" + stdout, stderr, err := podExecutor.Exec(ctx, strings.NewReader(sql), map[string]string{ + "ON_ERROR_STOP": "on", + "QUIET": "on", + }, []string{"-t"}) + if err != nil { + return "", errors.Wrapf(err, "execute query: stderr=%s", stderr) + } + + lsn := strings.TrimSpace(stdout) + if lsn == "" { + return "", errors.New("empty WAL LSN result") + } + return lsn, nil +} + +func (r *PGClusterReconciler) reconcileStandbyMainSiteAnnotation(ctx context.Context, cr *v2.PerconaPGCluster) error { + if !cr.ShouldCheckStandbyLag() || cr.Spec.Standby.RepoName == "" { + return nil + } + + if _, ok := cr.GetAnnotations()[pNaming.AnnotationReplicationMainSite]; ok { + return nil + } + + mainSite, err := r.getStandbyMainSite(ctx, cr) + if err != nil { + return errors.Wrap(err, "get standby main site") + } + + log := logging.FromContext(ctx) + + mainSiteVal := "" + if mainSite != nil { + mainSiteVal = mainSite.GetNamespace() + "/" + mainSite.GetName() + } else { + log.V(1).Info("Main site not found in Kubernetes, cannot detect standby lag") + } + + crCopy := cr.DeepCopy() + if err := r.Client.Get(ctx, client.ObjectKeyFromObject(crCopy), crCopy); err != nil { + return errors.Wrap(err, "get cluster for main site annotation update") + } + + annots := crCopy.GetAnnotations() + if annots == nil { + annots = make(map[string]string) + } + annots[pNaming.AnnotationReplicationMainSite] = mainSiteVal + crCopy.SetAnnotations(annots) + if err := r.Client.Update(ctx, crCopy); err != nil { + return errors.Wrap(err, "update standby main site annotation") + } + return nil +} + +// getStandbyMainSite returns the name of the main site for the standby cluster (based on pgbackrest only) +func (r *PGClusterReconciler) getStandbyMainSite(ctx context.Context, cr *v2.PerconaPGCluster) (*v2.PerconaPGCluster, error) { + if !cr.ShouldCheckStandbyLag() || cr.Spec.Standby.RepoName == "" { + return nil, errors.New("standby cluster is not enabled or repo name is not specified") + } + + targetRepo := v1beta1.PGBackRestRepo{} + for _, repo := range cr.Spec.Backups.PGBackRest.Repos { + if repo.Name == cr.Spec.Standby.RepoName { + targetRepo = repo + break + } + } + + if targetRepo.Name == "" { + return nil, errors.New("standby repo name not found in list of repos") + } + + listOptions := []client.ListOption{} + if len(r.WatchNamespace) == 1 { + listOptions = append(listOptions, client.InNamespace(cr.Namespace)) + } + clusters := &v2.PerconaPGClusterList{} + if err := r.Client.List(ctx, clusters, listOptions...); err != nil { + return nil, errors.Wrap(err, "list clusters") + } + + for _, cluster := range clusters.Items { + if cluster.Name == cr.Name { + continue + } + if cluster.Spec.Standby != nil && cluster.Spec.Standby.Enabled { + continue + } + for _, repo := range cluster.Spec.Backups.PGBackRest.Repos { + if targetRepo.StorageEquals(&repo) { + return cluster.DeepCopy(), nil + } + } + } + return nil, nil +} + +// pollAndRequeueStandbys periodically polls the clusters and requeues those standbys that need to be checked for lag. +func pollAndRequeueStandbys( + ctx context.Context, + events chan event.GenericEvent, + cl client.Client, + namespace string) { + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + log := logging.FromContext(ctx).WithName("PollStandbys") + for { + select { + case <-ticker.C: + clusters := &v2.PerconaPGClusterList{} + + listOptions := []client.ListOption{} + if namespace != "" { + listOptions = append(listOptions, client.InNamespace(namespace)) + } + if err := cl.List(ctx, clusters, listOptions...); err != nil { + log.Error(err, "list clusters") + continue + } + + for _, cluster := range clusters.Items { + status := cluster.Status + if !cluster.ShouldCheckStandbyLag() || status.Standby == nil || shouldSkipLagCheck(&cluster) { + continue + } + log.Info("Requeuing standby cluster for lag check", "cluster", cluster.Name) + events <- event.GenericEvent{Object: cluster.DeepCopy()} + } + case <-ctx.Done(): + log.Info("Stopping poll and requeue standbys") + return + } + } +} diff --git a/percona/controller/pgcluster/standby_test.go b/percona/controller/pgcluster/standby_test.go new file mode 100644 index 0000000000..402edc6aa3 --- /dev/null +++ b/percona/controller/pgcluster/standby_test.go @@ -0,0 +1,544 @@ +package pgcluster + +import ( + "context" + "fmt" + "io" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +func TestReconcileStandbyLag(t *testing.T) { + sourceCluster, err := readDefaultCR("source-cluster", "default") + require.NoError(t, err) + sourceCluster.Default() + + standbyCluster, err := readDefaultCR("standby-cluster", "default") + require.NoError(t, err) + standbyCluster.Default() + standbyCluster.Spec.Standby = &v2.StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: true, + RepoName: "repo1", + }, + MaxAcceptableLag: ptr.To(resource.MustParse("1Mi")), + } + standbyCluster.Status.State = v2.AppStateReady + standbyCluster.SetAnnotations(map[string]string{ + pNaming.AnnotationReplicationMainSite: sourceCluster.GetNamespace() + "/" + sourceCluster.GetName(), + }) + + mockPodExec := func(wantLagBytes int64) func(context.Context, string, string, string, io.Reader, io.Writer, io.Writer, ...string) error { + return func(ctx context.Context, namespace, pod, container string, + stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + + if stdin == nil { + return nil + } + + sqlB, err := io.ReadAll(stdin) + if err != nil { + return err + } + + query := strings.TrimSpace(string(sqlB)) + if strings.Contains(query, "pg_current_wal_lsn") { + fmt.Fprint(stdout, "0/12345678\n") + } else if strings.Contains(query, "pg_wal_lsn_diff") { + fmt.Fprintf(stdout, "%d\n", wantLagBytes) + } + return nil + } + } + + newReconciler := func( + sourceCluster *v2.PerconaPGCluster, + standbyCluster *v2.PerconaPGCluster, + sourcePrimary *corev1.Pod, + standbyPrimary *corev1.Pod, + ) *PGClusterReconciler { + cl, err := buildFakeClient(t.Context(), sourceCluster, standbyCluster, sourcePrimary, standbyPrimary) + require.NoError(t, err) + + return &PGClusterReconciler{ + Client: cl, + } + } + + t.Run("CRVersion < 2.9.0", func(t *testing.T) { + cluster := standbyCluster.DeepCopy() + cluster.Spec.CRVersion = "2.8.0" + + r := newReconciler( + sourceCluster, + cluster, + primaryPodForCluster(sourceCluster), + primaryPodForCluster(cluster), + ) + r.PodExec = mockPodExec(0) + + err := r.reconcileStandbyLag(t.Context(), cluster) + require.NoError(t, err) + + cond := meta.FindStatusCondition(cluster.Status.Conditions, postgrescluster.ConditionStandbyLagging) + assert.Nil(t, cond) + assert.Nil(t, cluster.Status.Standby) + }) + + t.Run("Standby not enabled", func(t *testing.T) { + cluster := standbyCluster.DeepCopy() + cluster.Spec.Standby.Enabled = false + + r := newReconciler( + sourceCluster, + cluster, + primaryPodForCluster(sourceCluster), + primaryPodForCluster(cluster), + ) + r.PodExec = mockPodExec(0) + + err := r.reconcileStandbyLag(t.Context(), cluster) + require.NoError(t, err) + + cond := meta.FindStatusCondition(cluster.Status.Conditions, postgrescluster.ConditionStandbyLagging) + assert.Nil(t, cond) + assert.Nil(t, cluster.Status.Standby) + }) + + t.Run("main site not found", func(t *testing.T) { + cluster := standbyCluster.DeepCopy() + cluster.SetAnnotations(map[string]string{}) + + r := newReconciler( + sourceCluster, + cluster, + primaryPodForCluster(sourceCluster), + primaryPodForCluster(cluster), + ) + r.PodExec = mockPodExec(0) + + err := r.reconcileStandbyLag(t.Context(), cluster) + require.NoError(t, err) + + cond := meta.FindStatusCondition(cluster.Status.Conditions, postgrescluster.ConditionStandbyLagging) + assert.NotNil(t, cond) + assert.Equal(t, metav1.ConditionUnknown, cond.Status) + assert.Equal(t, "MainSiteNotFound", cond.Reason) + }) + + t.Run("lag not detected", func(t *testing.T) { + cluster := standbyCluster.DeepCopy() + r := newReconciler( + sourceCluster, + cluster, + primaryPodForCluster(sourceCluster), + primaryPodForCluster(cluster), + ) + r.PodExec = mockPodExec(0) + + err = r.reconcileStandbyLag(t.Context(), cluster) + require.NoError(t, err) + + cond := meta.FindStatusCondition(cluster.Status.Conditions, postgrescluster.ConditionStandbyLagging) + assert.NotNil(t, cond) + assert.Equal(t, metav1.ConditionFalse, cond.Status) + + assert.NotNil(t, cluster.Status.Standby) + assert.NotNil(t, cluster.Status.Standby.LagLastComputedAt) + assert.Equal(t, int64(0), cluster.Status.Standby.LagBytes) + }) + + t.Run("lag below threshold", func(t *testing.T) { + cluster := standbyCluster.DeepCopy() + r := newReconciler( + sourceCluster, + cluster, + primaryPodForCluster(sourceCluster), + primaryPodForCluster(standbyCluster), + ) + r.PodExec = mockPodExec(1024) + + err = r.reconcileStandbyLag(t.Context(), cluster) + require.NoError(t, err) + + cond := meta.FindStatusCondition(cluster.Status.Conditions, postgrescluster.ConditionStandbyLagging) + assert.NotNil(t, cond) + assert.Equal(t, metav1.ConditionFalse, cond.Status) + assert.Equal(t, int64(1024), cluster.Status.Standby.LagBytes) + }) + + t.Run("lag above threshold", func(t *testing.T) { + cluster := standbyCluster.DeepCopy() + now := time.Now() + now = now.Add(-defaultReplicationLagDetectionInterval) + cluster.Status.Standby = &v2.StandbyStatus{ + LagLastComputedAt: ptr.To(metav1.Time{Time: now}), + } + r := newReconciler( + sourceCluster, + cluster, + primaryPodForCluster(sourceCluster), + primaryPodForCluster(cluster), + ) + r.PodExec = mockPodExec(3 * 1024 * 1024) + + err = r.reconcileStandbyLag(t.Context(), cluster) + require.NoError(t, err) + + cond := meta.FindStatusCondition(cluster.Status.Conditions, postgrescluster.ConditionStandbyLagging) + assert.NotNil(t, cond) + assert.Equal(t, metav1.ConditionTrue, cond.Status) + }) +} + +func primaryPodForCluster(cluster *v2.PerconaPGCluster) *corev1.Pod { + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: cluster.Name + "-primary-xyz-0", + Namespace: cluster.Namespace, + Labels: map[string]string{ + "app.kubernetes.io/instance": cluster.Name, + "postgres-operator.crunchydata.com/role": "primary", + }, + }, + } +} + +func TestGetStandbyMainSite(t *testing.T) { + // Prepare mocks objects + sourceCluster, err := readDefaultCR("source-cluster", "default") + require.NoError(t, err) + sourceCluster.Default() + sourceCluster.Spec.Backups.PGBackRest.Repos = []crunchyv1beta1.PGBackRestRepo{ + { + Name: "repo1", + S3: &crunchyv1beta1.RepoS3{ + Bucket: "some-bucket", + Endpoint: "some-endpoint", + Region: "some-region", + }, + }, + } + + standbyCluster, err := readDefaultCR("standby-cluster", "default") + require.NoError(t, err) + standbyCluster.Default() + standbyCluster.Spec.Backups.PGBackRest.Repos = []crunchyv1beta1.PGBackRestRepo{ + { + Name: "repo1", + S3: &crunchyv1beta1.RepoS3{ + Bucket: "some-bucket", + Endpoint: "some-endpoint", + Region: "some-region", + }, + }, + } + standbyCluster.Spec.Standby = &v2.StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: true, + RepoName: "repo1", + }, + MaxAcceptableLag: ptr.To(resource.MustParse("1Mi")), + } + + t.Run("standby not enabled", func(t *testing.T) { + standby := standbyCluster.DeepCopy() + standby.Spec.Standby.Enabled = false + + cl, err := buildFakeClient(t.Context(), standbyCluster, []client.Object{sourceCluster}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + _, err = r.getStandbyMainSite(t.Context(), standby) + assert.Error(t, err) + }) + + t.Run("standby repo not specified", func(t *testing.T) { + standby := standbyCluster.DeepCopy() + standby.Spec.Standby.RepoName = "" + + cl, err := buildFakeClient(t.Context(), standbyCluster, []client.Object{sourceCluster}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + _, err = r.getStandbyMainSite(t.Context(), standby) + assert.Error(t, err) + }) + + t.Run("source cluster with different repo configuration", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + + source.Spec.Backups.PGBackRest.Repos = []crunchyv1beta1.PGBackRestRepo{ + { + Name: "repo1", + S3: &crunchyv1beta1.RepoS3{ + Bucket: "different-bucket", + Endpoint: "some-endpoint", + Region: "some-region", + }, + }, + } + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + mainSite, err := r.getStandbyMainSite(t.Context(), standby) + require.NoError(t, err) + assert.Nil(t, mainSite) + }) + + t.Run("source cluster in same namespace", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + mainSite, err := r.getStandbyMainSite(t.Context(), standby) + require.NoError(t, err) + assert.NotNil(t, mainSite) + assert.Equal(t, source.GetNamespace(), mainSite.GetNamespace()) + assert.Equal(t, source.GetName(), mainSite.GetName()) + }) + + t.Run("source cluster in different namespace", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + source.Namespace = "different-namespace" + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + mainSite, err := r.getStandbyMainSite(t.Context(), standby) + require.NoError(t, err) + assert.NotNil(t, mainSite) + assert.Equal(t, "different-namespace", mainSite.GetNamespace()) + assert.Equal(t, source.GetName(), mainSite.GetName()) + }) + + t.Run("non-cluster-wide mode", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + + source.Namespace = "different-namespace" + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + WatchNamespace: []string{"default"}, + } + + mainSite, err := r.getStandbyMainSite(t.Context(), standby) + require.NoError(t, err) + assert.Nil(t, mainSite) + }) +} + +func TestReconcileStandbyMainSiteAnnotation(t *testing.T) { + // Prepare mocks objects + sourceCluster, err := readDefaultCR("source-cluster", "default") + require.NoError(t, err) + sourceCluster.Default() + sourceCluster.Spec.Backups.PGBackRest.Repos = []crunchyv1beta1.PGBackRestRepo{ + { + Name: "repo1", + S3: &crunchyv1beta1.RepoS3{ + Bucket: "some-bucket", + Endpoint: "some-endpoint", + Region: "some-region", + }, + }, + } + + standbyCluster, err := readDefaultCR("standby-cluster", "default") + require.NoError(t, err) + standbyCluster.Default() + standbyCluster.Spec.Backups.PGBackRest.Repos = []crunchyv1beta1.PGBackRestRepo{ + { + Name: "repo1", + S3: &crunchyv1beta1.RepoS3{ + Bucket: "some-bucket", + Endpoint: "some-endpoint", + Region: "some-region", + }, + }, + } + standbyCluster.Spec.Standby = &v2.StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: true, + RepoName: "repo1", + }, + MaxAcceptableLag: ptr.To(resource.MustParse("1Mi")), + } + + t.Run("standby not enabled", func(t *testing.T) { + standby := standbyCluster.DeepCopy() + standby.Spec.Standby.Enabled = false + + cl, err := buildFakeClient(t.Context(), standbyCluster, []client.Object{sourceCluster}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + err = r.reconcileStandbyMainSiteAnnotation(t.Context(), standby) + require.NoError(t, err) + + observedCR := &v2.PerconaPGCluster{} + err = cl.Get(t.Context(), client.ObjectKeyFromObject(standby), observedCR) + require.NoError(t, err) + assert.Empty(t, observedCR.GetAnnotations()[pNaming.AnnotationReplicationMainSite]) + }) + + t.Run("standby repo not specified", func(t *testing.T) { + standby := standbyCluster.DeepCopy() + standby.Spec.Standby.RepoName = "" + + cl, err := buildFakeClient(t.Context(), standbyCluster, []client.Object{sourceCluster}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + err = r.reconcileStandbyMainSiteAnnotation(t.Context(), standby) + require.NoError(t, err) + + observedCR := &v2.PerconaPGCluster{} + err = cl.Get(t.Context(), client.ObjectKeyFromObject(standby), observedCR) + require.NoError(t, err) + assert.Empty(t, observedCR.GetAnnotations()[pNaming.AnnotationReplicationMainSite]) + }) + + t.Run("source cluster with different repo configuration", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + + source.Spec.Backups.PGBackRest.Repos = []crunchyv1beta1.PGBackRestRepo{ + { + Name: "repo1", + S3: &crunchyv1beta1.RepoS3{ + Bucket: "different-bucket", + Endpoint: "some-endpoint", + Region: "some-region", + }, + }, + } + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + err = r.reconcileStandbyMainSiteAnnotation(t.Context(), standby) + require.NoError(t, err) + + observedCR := &v2.PerconaPGCluster{} + err = cl.Get(t.Context(), client.ObjectKeyFromObject(standby), observedCR) + require.NoError(t, err) + assert.Empty(t, observedCR.GetAnnotations()[pNaming.AnnotationReplicationMainSite]) + }) + + t.Run("source cluster in same namespace", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + err = r.reconcileStandbyMainSiteAnnotation(t.Context(), standby) + require.NoError(t, err) + + observedCR := &v2.PerconaPGCluster{} + err = cl.Get(t.Context(), client.ObjectKeyFromObject(standby), observedCR) + require.NoError(t, err) + assert.Equal(t, source.GetNamespace()+"/"+source.GetName(), observedCR.GetAnnotations()[pNaming.AnnotationReplicationMainSite]) + }) + + t.Run("source cluster in different namespace", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + source.Namespace = "different-namespace" + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + } + + err = r.reconcileStandbyMainSiteAnnotation(t.Context(), standby) + require.NoError(t, err) + + observedCR := &v2.PerconaPGCluster{} + err = cl.Get(t.Context(), client.ObjectKeyFromObject(standby), observedCR) + require.NoError(t, err) + assert.Equal(t, source.GetNamespace()+"/"+source.GetName(), observedCR.GetAnnotations()[pNaming.AnnotationReplicationMainSite]) + }) + + t.Run("non-cluster-wide mode", func(t *testing.T) { + source := sourceCluster.DeepCopy() + standby := standbyCluster.DeepCopy() + + source.Namespace = "different-namespace" + + cl, err := buildFakeClient(t.Context(), standby, []client.Object{source}...) + require.NoError(t, err) + + r := &PGClusterReconciler{ + Client: cl, + WatchNamespace: []string{"default"}, + } + + err = r.reconcileStandbyMainSiteAnnotation(t.Context(), standby) + require.NoError(t, err) + + observedCR := &v2.PerconaPGCluster{} + err = cl.Get(t.Context(), client.ObjectKeyFromObject(standby), observedCR) + require.NoError(t, err) + assert.Empty(t, observedCR.GetAnnotations()[pNaming.AnnotationReplicationMainSite]) + }) +} diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index d0491462db..1039e96fec 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -2,6 +2,7 @@ package pgcluster import ( "context" + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -121,6 +122,10 @@ func (r *PGClusterReconciler) updateStatus(ctx context.Context, cr *v2.PerconaPG cluster.Status.State = r.getState(cr, &cluster.Status, status) + if err := r.reconcileStandbyLag(ctx, cluster); err != nil { + return errors.Wrap(err, "reconcile replication lag status") + } + cluster.Status.ObservedGeneration = cluster.Generation updateConditions(cluster, status) diff --git a/percona/naming/annotations.go b/percona/naming/annotations.go index dadb4242c8..cf36f7b6bc 100644 --- a/percona/naming/annotations.go +++ b/percona/naming/annotations.go @@ -46,4 +46,9 @@ const ( // Special annotation to disable `patroni-version-check` by overriding the patroni version with a custom value. AnnotationCustomPatroniVersion = PrefixPerconaPGV2 + "custom-patroni-version" + + // AnnotationReplicationMainSite is the annotation that is added to a standby PerconaPGCluster to + // indicate the name of the main site. + // This annotation is set on standby clusters based on pgbackrest only. This is needed to calculate the replication lag. + AnnotationReplicationMainSite = PrefixPerconaPGV2 + "replication-main-site" ) diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 613ae8fe15..cbef05d958 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -5,6 +5,7 @@ import ( gover "github.com/hashicorp/go-version" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" @@ -103,7 +104,7 @@ type PerconaPGClusterSpec struct { // Run this cluster as a read-only copy of an existing cluster or archive. // +optional - Standby *crunchyv1beta1.PostgresStandbySpec `json:"standby,omitempty"` + Standby *StandbySpec `json:"standby,omitempty"` // Whether or not the PostgreSQL cluster is being deployed to an OpenShift // environment. If the field is unset, the operator will automatically @@ -175,6 +176,24 @@ type PerconaPGClusterSpec struct { AutoCreateUserSchema *bool `json:"autoCreateUserSchema,omitempty"` } +type StandbySpec struct { + *crunchyv1beta1.PostgresStandbySpec `json:",inline"` + + // +optional + // MaxAcceptableLag is the maximum WAL lag allowed for the standby cluster, measured in bytes of WAL data. + // This represents the maximum amount of WAL data that the standby can be behind the primary. + // If the lag exceeds this value, the standby cluster is marked as unready. + // If unset, lag is not checked. + MaxAcceptableLag *resource.Quantity `json:"maxAcceptableLag,omitempty"` +} + +func (cr *PerconaPGCluster) ShouldCheckStandbyLag() bool { + return cr.CompareVersion("2.9.0") >= 0 && + cr.Spec.Standby != nil && + cr.Spec.Standby.Enabled && + cr.Spec.Standby.MaxAcceptableLag != nil +} + func (cr *PerconaPGCluster) Default() { if len(cr.Spec.CRVersion) == 0 { cr.Spec.CRVersion = version.Version() @@ -304,7 +323,10 @@ func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crun postgresCluster.Spec.OpenShift = cr.Spec.OpenShift postgresCluster.Spec.Paused = cr.Spec.Unmanaged postgresCluster.Spec.Shutdown = cr.Spec.Pause - postgresCluster.Spec.Standby = cr.Spec.Standby + + if cr.Spec.Standby != nil { + postgresCluster.Spec.Standby = cr.Spec.Standby.PostgresStandbySpec + } postgresCluster.Spec.Service = cr.Spec.Expose.ToCrunchy(cr.Spec.CRVersion) postgresCluster.Spec.ReplicaService = cr.Spec.ExposeReplicas.ToCrunchy(cr.Spec.CRVersion) @@ -470,6 +492,15 @@ type PerconaPGClusterStatus struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=status ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status + Standby *StandbyStatus `json:"standby,omitempty"` +} + +type StandbyStatus struct { + LagLastComputedAt *metav1.Time `json:"lagLastComputedAt,omitempty"` + LagBytes int64 `json:"lagBytes,omitempty"` } type Patroni struct { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go index fe0fc77d90..5f9cfd68be 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go @@ -9,8 +9,10 @@ import ( "github.com/stretchr/testify/require" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + k8sptr "k8s.io/utils/ptr" "github.com/percona/percona-postgresql-operator/v2/internal/naming" "github.com/percona/percona-postgresql-operator/v2/percona/version" @@ -382,3 +384,107 @@ func contains(slice []string, item string) bool { } return false } + +func TestShouldCheckStandbyLag(t *testing.T) { + testCases := []struct { + descr string + expected bool + cr *PerconaPGCluster + }{ + { + descr: "CRVersion < 2.9.0", + cr: &PerconaPGCluster{ + Spec: PerconaPGClusterSpec{ + CRVersion: "2.8.0", + }, + }, + expected: false, + }, + { + descr: "CRVersion < 2.9.0, standby!=nil", + cr: &PerconaPGCluster{ + Spec: PerconaPGClusterSpec{ + CRVersion: "2.8.0", + Standby: &StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: true, + }, + }, + }, + }, + expected: false, + }, + { + descr: "CRVersion = 2.9.0, standby.enabled=true", + cr: &PerconaPGCluster{ + Spec: PerconaPGClusterSpec{ + CRVersion: "2.8.0", + Standby: &StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: true, + }, + }, + }, + }, + expected: false, + }, + { + descr: "standby=nil", + cr: &PerconaPGCluster{ + Spec: PerconaPGClusterSpec{ + CRVersion: "2.9.0", + }, + }, + expected: false, + }, + { + descr: "standby.enabled=false", + cr: &PerconaPGCluster{ + Spec: PerconaPGClusterSpec{ + CRVersion: "2.9.0", + Standby: &StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: false, + }, + }, + }, + }, + expected: false, + }, + { + descr: "standby.enabled=true, maxAcceptableLag=nil", + cr: &PerconaPGCluster{ + Spec: PerconaPGClusterSpec{ + CRVersion: "2.9.0", + Standby: &StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: false, + }, + }, + }, + }, + expected: false, + }, + { + descr: "standby.enabled=true, maxAcceptableLag=0", + cr: &PerconaPGCluster{ + Spec: PerconaPGClusterSpec{ + CRVersion: "2.9.0", + Standby: &StandbySpec{ + PostgresStandbySpec: &crunchyv1beta1.PostgresStandbySpec{ + Enabled: true, + }, + MaxAcceptableLag: k8sptr.To(resource.MustParse("0")), + }, + }, + }, + expected: true, + }, + } + + for _, tt := range testCases { + t.Run(tt.descr, func(t *testing.T) { + assert.Equal(t, tt.expected, tt.cr.ShouldCheckStandbyLag()) + }) + } +} diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index 1409dcf859..815d6481af 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -769,7 +769,7 @@ func (in *PerconaPGClusterSpec) DeepCopyInto(out *PerconaPGClusterSpec) { in.Secrets.DeepCopyInto(&out.Secrets) if in.Standby != nil { in, out := &in.Standby, &out.Standby - *out = new(v1beta1.PostgresStandbySpec) + *out = new(StandbySpec) (*in).DeepCopyInto(*out) } if in.OpenShift != nil { @@ -868,6 +868,11 @@ func (in *PerconaPGClusterStatus) DeepCopyInto(out *PerconaPGClusterStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Standby != nil { + in, out := &in.Standby, &out.Standby + *out = new(StandbyStatus) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PerconaPGClusterStatus. @@ -1210,3 +1215,47 @@ func (in *ServiceExpose) DeepCopy() *ServiceExpose { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StandbySpec) DeepCopyInto(out *StandbySpec) { + *out = *in + if in.PostgresStandbySpec != nil { + in, out := &in.PostgresStandbySpec, &out.PostgresStandbySpec + *out = new(v1beta1.PostgresStandbySpec) + (*in).DeepCopyInto(*out) + } + if in.MaxAcceptableLag != nil { + in, out := &in.MaxAcceptableLag, &out.MaxAcceptableLag + x := (*in).DeepCopy() + *out = &x + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StandbySpec. +func (in *StandbySpec) DeepCopy() *StandbySpec { + if in == nil { + return nil + } + out := new(StandbySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StandbyStatus) DeepCopyInto(out *StandbyStatus) { + *out = *in + if in.LagLastComputedAt != nil { + in, out := &in.LagLastComputedAt, &out.LagLastComputedAt + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StandbyStatus. +func (in *StandbyStatus) DeepCopy() *StandbyStatus { + if in == nil { + return nil + } + out := new(StandbyStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go index 91a2b220f9..e7dc6f39ea 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types.go @@ -5,6 +5,8 @@ package v1beta1 import ( + "reflect" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -486,3 +488,34 @@ type PGBackRestDataSource struct { // +optional Tolerations []corev1.Toleration `json:"tolerations,omitempty"` } + +func (r *PGBackRestRepo) StorageEquals(other *PGBackRestRepo) bool { + switch { + case r.Azure != nil && other.Azure != nil: + return r.Azure.Equals(other.Azure) + case r.GCS != nil && other.GCS != nil: + return r.GCS.Equals(other.GCS) + case r.S3 != nil && other.S3 != nil: + return r.S3.Equals(other.S3) + case r.Volume != nil && other.Volume != nil: + return r.Volume.Equals(other.Volume) + default: + return false + } +} + +func (r *RepoAzure) Equals(other *RepoAzure) bool { + return r.Container == other.Container +} + +func (r *RepoGCS) Equals(other *RepoGCS) bool { + return r.Bucket == other.Bucket +} + +func (r *RepoS3) Equals(other *RepoS3) bool { + return r.Bucket == other.Bucket && r.Endpoint == other.Endpoint && r.Region == other.Region +} + +func (r *RepoPVC) Equals(other *RepoPVC) bool { + return reflect.DeepEqual(r.VolumeClaimSpec, other.VolumeClaimSpec) +} diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types_test.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types_test.go new file mode 100644 index 0000000000..8ae3e02204 --- /dev/null +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/pgbackrest_types_test.go @@ -0,0 +1,462 @@ +package v1beta1 + +import ( + "testing" + + "gotest.tools/v3/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/utils/ptr" +) + +func TestPGBackRestRepo_StorageEquals(t *testing.T) { + testCases := []struct { + name string + repoA *PGBackRestRepo + repoB *PGBackRestRepo + expected bool + }{ + // S3 repo tests + { + name: "S3 repos with same values", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + expected: true, + }, + { + name: "S3 repos with different bucket", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "other-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + expected: false, + }, + { + name: "S3 repos with different endpoint", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.us-west-2.amazonaws.com", + Region: "us-east-1", + }, + }, + expected: false, + }, + { + name: "S3 repos with different region", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-west-2", + }, + }, + expected: false, + }, + // GCS repo tests + { + name: "GCS repos with same values", + repoA: &PGBackRestRepo{ + Name: "repo1", + GCS: &RepoGCS{ + Bucket: "my-gcs-bucket", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + GCS: &RepoGCS{ + Bucket: "my-gcs-bucket", + }, + }, + expected: true, + }, + { + name: "GCS repos with different bucket", + repoA: &PGBackRestRepo{ + Name: "repo1", + GCS: &RepoGCS{ + Bucket: "my-gcs-bucket", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + GCS: &RepoGCS{ + Bucket: "other-gcs-bucket", + }, + }, + expected: false, + }, + // Azure repo tests + { + name: "Azure repos with same values", + repoA: &PGBackRestRepo{ + Name: "repo1", + Azure: &RepoAzure{ + Container: "my-container", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Azure: &RepoAzure{ + Container: "my-container", + }, + }, + expected: true, + }, + { + name: "Azure repos with different container", + repoA: &PGBackRestRepo{ + Name: "repo1", + Azure: &RepoAzure{ + Container: "my-container", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Azure: &RepoAzure{ + Container: "other-container", + }, + }, + expected: false, + }, + // Volume repo tests + { + name: "Volume repos with same values", + repoA: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + expected: true, + }, + { + name: "Volume repos with different storage size", + repoA: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("2Gi"), + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "Volume repos with different access modes", + repoA: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteMany}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "Volume repos with different storage class", + repoA: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + StorageClassName: ptr.To("standard"), + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + StorageClassName: ptr.To("premium"), + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + expected: false, + }, + // Different repo types + { + name: "S3 vs GCS", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + GCS: &RepoGCS{ + Bucket: "my-bucket", + }, + }, + expected: false, + }, + { + name: "S3 vs Azure", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Azure: &RepoAzure{ + Container: "my-container", + }, + }, + expected: false, + }, + { + name: "S3 vs Volume", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "GCS vs Azure", + repoA: &PGBackRestRepo{ + Name: "repo1", + GCS: &RepoGCS{ + Bucket: "my-bucket", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Azure: &RepoAzure{ + Container: "my-container", + }, + }, + expected: false, + }, + { + name: "GCS vs Volume", + repoA: &PGBackRestRepo{ + Name: "repo1", + GCS: &RepoGCS{ + Bucket: "my-bucket", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + expected: false, + }, + { + name: "Azure vs Volume", + repoA: &PGBackRestRepo{ + Name: "repo1", + Azure: &RepoAzure{ + Container: "my-container", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + Volume: &RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + expected: false, + }, + // Nil cases + { + name: "Both repos have nil storage", + repoA: &PGBackRestRepo{ + Name: "repo1", + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + }, + expected: false, + }, + { + name: "RepoA has S3, RepoB has nil", + repoA: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + }, + expected: false, + }, + { + name: "RepoA has nil, RepoB has S3", + repoA: &PGBackRestRepo{ + Name: "repo1", + }, + repoB: &PGBackRestRepo{ + Name: "repo1", + S3: &RepoS3{ + Bucket: "my-bucket", + Endpoint: "s3.amazonaws.com", + Region: "us-east-1", + }, + }, + expected: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := tc.repoA.StorageEquals(tc.repoB) + assert.Equal(t, tc.expected, actual) + }) + } +} From 507c7162578d93ce99e3b32b952743fc71916f1b Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 10 Feb 2026 16:48:38 +0100 Subject: [PATCH 285/300] fix condition --- percona/controller/pgcluster/backup.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index ae3402125c..a83f835c54 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -49,13 +49,16 @@ func (r *PGClusterReconciler) cleanupOutdatedBackups(ctx context.Context, cr *v2 return nil } - repoCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionRepoHostReady) - if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { - log.Info("pgBackRest repo host not ready, skipping backup cleanup") - return nil - } - for _, repo := range cr.Spec.Backups.PGBackRest.Repos { + + if repo.Volume != nil { + repoCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionRepoHostReady) + if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { + log.Info("pgBackRest repo host not ready, skipping backup cleanup", "repo", repo.Name) + continue + } + } + var info pgbackrest.InfoOutput pbList, err := listPGBackups(ctx, r.Client, cr, repo.Name) From 948c79395b979751c1ed19e3a8e60c723e018ab2 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 10 Feb 2026 16:50:11 +0100 Subject: [PATCH 286/300] fix condition delete space --- percona/controller/pgcluster/backup.go | 1 - 1 file changed, 1 deletion(-) diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index a83f835c54..06c680e258 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -50,7 +50,6 @@ func (r *PGClusterReconciler) cleanupOutdatedBackups(ctx context.Context, cr *v2 } for _, repo := range cr.Spec.Backups.PGBackRest.Repos { - if repo.Volume != nil { repoCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionRepoHostReady) if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { From a579e0e7a5c27463ad09127ad5b88311af86e476 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 10 Feb 2026 17:28:01 +0100 Subject: [PATCH 287/300] fix gke cluster test --- Jenkinsfile | 11 +++++ e2e-tests/functions | 100 ++++++-------------------------------------- 2 files changed, 23 insertions(+), 88 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7af7d55d18..56c11bb826 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -8,6 +8,13 @@ void createCluster(String CLUSTER_SUFFIX) { export KUBECONFIG=/tmp/$CLUSTER_NAME-${CLUSTER_SUFFIX} gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE gcloud config set project $GCP_PROJECT + + cat > ${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml </tmp/node-pool-config.yaml </dev/null; then - - echo "Node pool updated (regional cluster)" - - elif gcloud container node-pools update ${node_pool} \ - --cluster ${gke_cluster} \ - --zone ${gke_zone} \ - --project ${gke_project} \ - --system-config-from-file=/tmp/node-pool-config.yaml 2>/dev/null; then - - echo "Node pool updated (zonal cluster)" - else - echo "Failed to update node pool" - rm -f /tmp/node-pool-config.yaml - return 1 - fi - - echo "Waiting for nodes to restart..." - sleep 60 - kubectl wait --for=condition=Ready nodes --all --timeout=300s - - rm -f /tmp/node-pool-config.yaml - echo "Hugepages configured on GKE" - return 0 + if kubectl get node ${node_name} -o jsonpath='{.status.allocatable.hugepages-2Mi}' | grep -q '[0-9]'; then + echo "✓ Hugepages are already configured on nodes" + return 0 + else + echo "✗ Warning: Hugepages not found in node allocatable resources" + return 1 + fi } enable_hugepages_eks() { From 3217e96e2c98662184868b79cc3ab39926f2a2fa Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 11 Feb 2026 08:29:31 +0100 Subject: [PATCH 288/300] fix --- Jenkinsfile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 56c11bb826..c26d8c45dd 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,11 +9,12 @@ void createCluster(String CLUSTER_SUFFIX) { gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE gcloud config set project $GCP_PROJECT + cat > ${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml < Date: Wed, 11 Feb 2026 09:21:31 +0100 Subject: [PATCH 289/300] fix --- Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c26d8c45dd..b69f254e2e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,8 +9,7 @@ void createCluster(String CLUSTER_SUFFIX) { gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE gcloud config set project $GCP_PROJECT - - cat > ${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml < "${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml" <<'EOF' linuxConfig: hugepageConfig: hugepage_size2m: 1024 From 140bdc5e6866a3c4542b60e17e63fd59811fd2c9 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 11 Feb 2026 10:05:30 +0100 Subject: [PATCH 290/300] fix --- Jenkinsfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index b69f254e2e..79e1fbcc7e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,11 +9,11 @@ void createCluster(String CLUSTER_SUFFIX) { gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE gcloud config set project $GCP_PROJECT - cat > "${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml" <<'EOF' - linuxConfig: - hugepageConfig: - hugepage_size2m: 1024 - EOF + printf 'linuxConfig:\n hugepageConfig:\n hugepage_size2m: 1024\n' > \${WORKSPACE}/hugepages-config-\${CLUSTER_SUFFIX}.yaml + + echo "=== HUGEPAGES CONFIG CONTENT ===" + cat \${WORKSPACE}/hugepages-config-\${CLUSTER_SUFFIX}.yaml + echo "=== END CONFIG ===" ret_num=0 while [ \${ret_num} -lt 15 ]; do From 4d4f0effda7404f7228d6f5ca4e6ff7748bc9491 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 11 Feb 2026 10:47:39 +0100 Subject: [PATCH 291/300] fix --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 79e1fbcc7e..505965725c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,10 +9,10 @@ void createCluster(String CLUSTER_SUFFIX) { gcloud auth activate-service-account --key-file $CLIENT_SECRET_FILE gcloud config set project $GCP_PROJECT - printf 'linuxConfig:\n hugepageConfig:\n hugepage_size2m: 1024\n' > \${WORKSPACE}/hugepages-config-\${CLUSTER_SUFFIX}.yaml + printf 'linuxConfig:\n hugepageConfig:\n hugepage_size2m: 1024\n' > ${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml echo "=== HUGEPAGES CONFIG CONTENT ===" - cat \${WORKSPACE}/hugepages-config-\${CLUSTER_SUFFIX}.yaml + cat ${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml echo "=== END CONFIG ===" ret_num=0 From 72f165fa63e55f27ea3edd001e9fe1d9e6e57d4e Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Wed, 11 Feb 2026 15:26:20 +0100 Subject: [PATCH 292/300] delete debug info --- Jenkinsfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 505965725c..29525a0bba 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,10 +11,6 @@ void createCluster(String CLUSTER_SUFFIX) { printf 'linuxConfig:\n hugepageConfig:\n hugepage_size2m: 1024\n' > ${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml - echo "=== HUGEPAGES CONFIG CONTENT ===" - cat ${WORKSPACE}/hugepages-config-${CLUSTER_SUFFIX}.yaml - echo "=== END CONFIG ===" - ret_num=0 while [ \${ret_num} -lt 15 ]; do ret_val=0 From 74b9009eb0943e7fe50076b0d4e643f5a02ea5fa Mon Sep 17 00:00:00 2001 From: Mayank Shah Date: Thu, 12 Feb 2026 18:29:50 +0530 Subject: [PATCH 293/300] add nil check before assigning to map (#1437) Signed-off-by: Mayank Shah --- percona/controller/pgcluster/patroniversion.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/percona/controller/pgcluster/patroniversion.go b/percona/controller/pgcluster/patroniversion.go index 50bf0addd6..bb9c1285b2 100644 --- a/percona/controller/pgcluster/patroniversion.go +++ b/percona/controller/pgcluster/patroniversion.go @@ -283,6 +283,9 @@ func (r *PGClusterReconciler) handleCustomPatroniVersionAnnotation(ctx context.C func (r *PGClusterReconciler) patchPatroniVersionAnnotation(ctx context.Context, cr *v2.PerconaPGCluster, patroniVersion string) error { orig := cr.DeepCopy() + if cr.Annotations == nil { + cr.Annotations = make(map[string]string) + } cr.Annotations[pNaming.AnnotationPatroniVersion] = patroniVersion if err := r.Client.Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil { return errors.Wrap(err, "failed to patch the pg cluster") From 0858be51dec4045c5c685512949016d53c94a216 Mon Sep 17 00:00:00 2001 From: Mayank Shah Date: Fri, 13 Feb 2026 14:31:35 +0530 Subject: [PATCH 294/300] Add Github Copilot instructions file (#1438) Signed-off-by: Mayank Shah --- .github/copilot-instructions.md | 75 +++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000000..e381850d06 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,75 @@ +# GitHub Copilot Code Review Instructions + +## Review Philosophy + +- Only comment when you have HIGH CONFIDENCE (>80%) that an issue exists +- Be concise +- Focus on actionable feedback, not observations +- If you're uncertain, stay silent—false positives reduce trust + +## Project Context + +Kubernetes Operator for PostgreSQL (Operator SDK, controller-runtime). Go + YAML. Key paths: `internal/`, `percona/`, `pkg/apis` and `e2e-tests/`. + +## Priority Areas + +### Security + +- Hardcoded secrets, credentials, or API keys +- SQL injection—use parameterized queries, never string concatenation +- Missing or overly broad RBAC (`+kubebuilder:rbac` on reconcile functions) +- Logging of secrets or sensitive data +- Unvalidated user input before DB operations + +### Correctness + +- Logic errors that could cause panics or incorrect behavior +- Race conditions, resource leaks (files, connections, memory) +- Incorrect or missing error propagation +- Error wrapping that doesn't add useful context +- Redundant comments that restate what the code shows + +### Imports and Dependencies + +- Use standard import aliases: `corev1`, `appsv1`, `metav1`, `apierrors`, etc. (per `.golangci.yaml`) +- Import order: standard, default, `github.com/percona` prefix + +### Controller / Reconcile Logic + +- Add `+kubebuilder:rbac` above reconcile functions that create/update K8s resources +- Set controller/owner references for owned resources +- Idempotent reconcile; handle `apierrors.IsConflict` with requeue + +### Logging + +- Prefer `logging.FromContext(ctx)` for loggers +- Use structured fields: `log.Info("message", "key", value)` +- Add logging for important operator actions (reconcile steps, errors, retries) + +### Testing + +- New features: expect unit tests and/or E2E (KUTTL) where appropriate +- Unit tests should use `assert` and `require` from `github.com/stretchr/testify` wherever applicable +- Utilize table driven tests when possible +- Test names should describe the scenario + +## Response Format + +When you identify an issue: + +1. **Problem** (1 sentence) +2. **Why it matters** (1 sentence, only if not obvious) +3. **Fix** (concrete suggestion or code snippet) + +Example: +``` +1. **Problem**: This map access can panic if the map is nil. +2. **Why it matters**: A panic can crash the operator and disrupt reconciliation. +3. **Fix**: Initialize the map before use, e.g. `m := make(map[string]string)` before assigning or reading. +``` + +## When to Stay Silent + +- You're uncertain whether something is an issue +- The concern is stylistic and the code is acceptable +- The fix would be a matter of preference, not correctness or security From f9b2aa76389a6bea2f13b09f3a89fd2e6e26473b Mon Sep 17 00:00:00 2001 From: Andrii Dema Date: Fri, 13 Feb 2026 11:56:11 +0200 Subject: [PATCH 295/300] K8SPG-694: add `clusterServiceDNSSuffix` (#1417) * K8SPG-694: add `clusterServiceDNSSuffix` https://perconadev.atlassian.net/browse/K8SPG-694 * revert change of `exposeSuperusers` * revert default annotations * fix `cr.yaml` * improve unit-tests --------- Co-authored-by: Viacheslav Sarzhan Co-authored-by: Mayank Shah --- ...ator.crunchydata.com_postgresclusters.yaml | 3 ++ .../pgv2.percona.com_perconapgclusters.yaml | 2 + .../pgv2.percona.com_perconapgclusters.yaml | 2 + ...ator.crunchydata.com_postgresclusters.yaml | 3 ++ deploy/bundle.yaml | 5 +++ deploy/cr.yaml | 1 + deploy/crd.yaml | 5 +++ deploy/cw-bundle.yaml | 5 +++ .../controller/postgrescluster/instance.go | 2 +- internal/controller/postgrescluster/pki.go | 8 ++-- .../controller/postgrescluster/pki_test.go | 10 ++--- internal/naming/dns.go | 20 ++++++---- internal/naming/dns_test.go | 37 +++++++++++++++++-- internal/pgbackrest/config.go | 30 +++++++-------- internal/pgbackrest/config_test.go | 17 ++++++--- internal/pgbackrest/reconcile.go | 27 +++++++------- internal/pgbouncer/reconcile.go | 2 +- .../v2/perconapgcluster_types.go | 3 ++ .../v1beta1/postgrescluster_types.go | 3 ++ 19 files changed, 126 insertions(+), 59 deletions(-) diff --git a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml index 5c929ad783..483add6462 100644 --- a/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/build/crd/crunchy/generated/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -6965,6 +6965,9 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + clusterServiceDNSSuffix: + description: K8SPG-694 + type: string config: properties: files: diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 8157921f7a..e8859d08e9 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -7116,6 +7116,8 @@ spec: are enabled rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) && size(self.pgbackrest.repos) > 0) + clusterServiceDNSSuffix: + type: string crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 118b07ebfe..6fcdbc3bb8 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -7521,6 +7521,8 @@ spec: are enabled rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) && size(self.pgbackrest.repos) > 0) + clusterServiceDNSSuffix: + type: string crVersion: description: |- Version of the operator. Update this to new version after operator diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 1275e6a397..edfd5ae9f1 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -6955,6 +6955,9 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + clusterServiceDNSSuffix: + description: K8SPG-694 + type: string config: properties: files: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 4a32231245..87e3aa52fe 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -7818,6 +7818,8 @@ spec: are enabled rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) && size(self.pgbackrest.repos) > 0) + clusterServiceDNSSuffix: + type: string crVersion: description: |- Version of the operator. Update this to new version after operator @@ -36871,6 +36873,9 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + clusterServiceDNSSuffix: + description: K8SPG-694 + type: string config: properties: files: diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 7c3476e844..599a19c21b 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -10,6 +10,7 @@ metadata: # - percona.com/delete-backups spec: crVersion: 2.9.0 +# clusterServiceDNSSuffix: cluster.local # initContainer: # image: docker.io/perconalab/percona-postgresql-operator:main # resources: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 80e7b33d46..0ae004e7cb 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -7818,6 +7818,8 @@ spec: are enabled rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) && size(self.pgbackrest.repos) > 0) + clusterServiceDNSSuffix: + type: string crVersion: description: |- Version of the operator. Update this to new version after operator @@ -36871,6 +36873,9 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + clusterServiceDNSSuffix: + description: K8SPG-694 + type: string config: properties: files: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 605143a4bc..11519a8144 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -7818,6 +7818,8 @@ spec: are enabled rule: (has(self.enabled) && self.enabled == false) || (has(self.pgbackrest.repos) && size(self.pgbackrest.repos) > 0) + clusterServiceDNSSuffix: + type: string crVersion: description: |- Version of the operator. Update this to new version after operator @@ -36871,6 +36873,9 @@ spec: description: Enable tracking latest restorable time type: boolean type: object + clusterServiceDNSSuffix: + description: K8SPG-694 + type: string config: properties: files: diff --git a/internal/controller/postgrescluster/instance.go b/internal/controller/postgrescluster/instance.go index b80da339d8..16f26b2c92 100644 --- a/internal/controller/postgrescluster/instance.go +++ b/internal/controller/postgrescluster/instance.go @@ -1498,7 +1498,7 @@ func (r *Reconciler) reconcileInstanceCertificates( var leafCert *pki.LeafCertificate if err == nil { - leafCert, err = r.instanceCertificate(ctx, instance, existing, instanceCerts, root) + leafCert, err = r.instanceCertificate(ctx, instance, existing, instanceCerts, root, cluster.Spec.ClusterServiceDNSSuffix) } if err == nil { err = patroni.InstanceCertificates(ctx, diff --git a/internal/controller/postgrescluster/pki.go b/internal/controller/postgrescluster/pki.go index 03a8bc200d..91fb5f6738 100644 --- a/internal/controller/postgrescluster/pki.go +++ b/internal/controller/postgrescluster/pki.go @@ -176,12 +176,12 @@ func (r *Reconciler) reconcileClusterCertificate( r.Client.Get(ctx, client.ObjectKeyFromObject(existing), existing))) leaf := &pki.LeafCertificate{} - primaryServiceDNSNames, err := naming.ServiceDNSNames(ctx, primaryService) + primaryServiceDNSNames, err := naming.ServiceDNSNames(ctx, primaryService, cluster.Spec.ClusterServiceDNSSuffix) if err != nil { return nil, errors.Wrap(err, "get primary service dns names") } - replicaServiceDNSNames, err := naming.ServiceDNSNames(ctx, replicaService) + replicaServiceDNSNames, err := naming.ServiceDNSNames(ctx, replicaService, cluster.Spec.ClusterServiceDNSSuffix) if err != nil { return nil, errors.Wrap(err, "get replica service dns names") } @@ -256,7 +256,7 @@ func (r *Reconciler) reconcileClusterCertificate( // using the current root certificate func (*Reconciler) instanceCertificate( ctx context.Context, instance *appsv1.StatefulSet, - existing, intent *corev1.Secret, root *pki.RootCertificateAuthority, + existing, intent *corev1.Secret, root *pki.RootCertificateAuthority, dnsSuffix string, ) ( *pki.LeafCertificate, error, ) { @@ -267,7 +267,7 @@ func (*Reconciler) instanceCertificate( // RFC 2818 states that the certificate DNS names must be used to verify // HTTPS identity. - dnsNames := naming.InstancePodDNSNames(ctx, instance) + dnsNames := naming.InstancePodDNSNames(ctx, instance, dnsSuffix) dnsFQDN := dnsNames[0] if err == nil { diff --git a/internal/controller/postgrescluster/pki_test.go b/internal/controller/postgrescluster/pki_test.go index cb6228a1bc..74541ac43f 100644 --- a/internal/controller/postgrescluster/pki_test.go +++ b/internal/controller/postgrescluster/pki_test.go @@ -188,7 +188,7 @@ func TestReconcileCerts(t *testing.T) { existing := &corev1.Secret{Data: make(map[string][]byte)} intent := &corev1.Secret{Data: make(map[string][]byte)} - initialLeafCert, err := r.instanceCertificate(ctx, instance, existing, intent, initialRoot) + initialLeafCert, err := r.instanceCertificate(ctx, instance, existing, intent, initialRoot, "") assert.NilError(t, err) fromSecret := &pki.LeafCertificate{} @@ -215,25 +215,23 @@ func TestReconcileCerts(t *testing.T) { existing := &corev1.Secret{Data: make(map[string][]byte)} intent := &corev1.Secret{Data: make(map[string][]byte)} - initialLeaf, err := r.instanceCertificate(ctx, instance, existing, intent, initialRoot) + initialLeaf, err := r.instanceCertificate(ctx, instance, existing, intent, initialRoot, "") assert.NilError(t, err) // reconcile the certificate - newLeaf, err := r.instanceCertificate(ctx, instance, existing, intent, newRootCert) + newLeaf, err := r.instanceCertificate(ctx, instance, existing, intent, newRootCert, "") assert.NilError(t, err) // assert old leaf cert does not match the newly reconciled one assert.Assert(t, !initialLeaf.Certificate.Equal(newLeaf.Certificate)) // 'reconcile' the certificate when the secret does not change. The returned leaf certificate should not change - newLeaf2, err := r.instanceCertificate(ctx, instance, intent, intent, newRootCert) + newLeaf2, err := r.instanceCertificate(ctx, instance, intent, intent, newRootCert, "") assert.NilError(t, err) // check that the leaf cert did not change after another reconciliation assert.DeepEqual(t, newLeaf2, newLeaf) - }) - }) t.Run("check cluster certificate secret reconciliation", func(t *testing.T) { diff --git a/internal/naming/dns.go b/internal/naming/dns.go index 243c83e833..76d28d4351 100644 --- a/internal/naming/dns.go +++ b/internal/naming/dns.go @@ -16,9 +16,9 @@ import ( // InstancePodDNSNames returns the possible DNS names for instance. The first // name is the fully qualified domain name (FQDN). -func InstancePodDNSNames(ctx context.Context, instance *appsv1.StatefulSet) []string { +func InstancePodDNSNames(ctx context.Context, instance *appsv1.StatefulSet, dnsSuffix string) []string { var ( - domain = KubernetesClusterDomain(ctx) + domain = KubernetesClusterDomain(ctx, dnsSuffix) namespace = instance.Namespace name = instance.Name + "-0." + instance.Spec.ServiceName ) @@ -36,7 +36,7 @@ func InstancePodDNSNames(ctx context.Context, instance *appsv1.StatefulSet) []st // RepoHostPodDNSNames returns the possible DNS names for a pgBackRest repository host Pod. // The first name is the fully qualified domain name (FQDN). -func RepoHostPodDNSNames(ctx context.Context, repoHost *appsv1.StatefulSet) ([]string, error) { +func RepoHostPodDNSNames(ctx context.Context, repoHost *appsv1.StatefulSet, dnsSuffix string) ([]string, error) { if repoHost.Namespace == "" { return nil, errors.New("repoHost.Namespace is empty") } @@ -48,7 +48,7 @@ func RepoHostPodDNSNames(ctx context.Context, repoHost *appsv1.StatefulSet) ([]s } var ( - domain = KubernetesClusterDomain(ctx) + domain = KubernetesClusterDomain(ctx, dnsSuffix) namespace = repoHost.Namespace name = repoHost.Name + "-0." + repoHost.Spec.ServiceName ) @@ -66,7 +66,7 @@ func RepoHostPodDNSNames(ctx context.Context, repoHost *appsv1.StatefulSet) ([]s // ServiceDNSNames returns the possible DNS names for service. The first name // is the fully qualified domain name (FQDN). -func ServiceDNSNames(ctx context.Context, service *corev1.Service) ([]string, error) { +func ServiceDNSNames(ctx context.Context, service *corev1.Service, dnsSuffix string) ([]string, error) { if service.Name == "" { return nil, errors.New("service.Name is empty") } @@ -75,7 +75,7 @@ func ServiceDNSNames(ctx context.Context, service *corev1.Service) ([]string, er return nil, errors.New("service.Namespace is empty") } - domain := KubernetesClusterDomain(ctx) + domain := KubernetesClusterDomain(ctx, dnsSuffix) return []string{ service.Name + "." + service.Namespace + ".svc." + domain, @@ -86,7 +86,13 @@ func ServiceDNSNames(ctx context.Context, service *corev1.Service) ([]string, er } // KubernetesClusterDomain looks up the Kubernetes cluster domain name. -func KubernetesClusterDomain(ctx context.Context) string { +// K8SPG-694: If the override parameter is provided, it is returned without performing any operations +func KubernetesClusterDomain(ctx context.Context, override string) string { + // K8SPG-694 + if override != "" { + return override + } + ctx, span := tracer.Start(ctx, "kubernetes-domain-lookup") defer span.End() diff --git a/internal/naming/dns_test.go b/internal/naming/dns_test.go index d9025e317f..148046cd49 100644 --- a/internal/naming/dns_test.go +++ b/internal/naming/dns_test.go @@ -16,7 +16,7 @@ import ( ) func TestInstancePodDNSNames(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) + ctx, cancel := context.WithTimeout(t.Context(), time.Second) defer cancel() instance := &appsv1.StatefulSet{} @@ -24,7 +24,7 @@ func TestInstancePodDNSNames(t *testing.T) { instance.Name = "cluster-name-id" instance.Spec.ServiceName = "cluster-pods" - names := InstancePodDNSNames(ctx, instance) + names := InstancePodDNSNames(ctx, instance, "") assert.Assert(t, len(names) > 0) assert.DeepEqual(t, names[1:], []string{ @@ -36,17 +36,31 @@ func TestInstancePodDNSNames(t *testing.T) { assert.Assert(t, len(names[0]) > len(names[1]), "expected FQDN first, got %q", names[0]) assert.Assert(t, strings.HasPrefix(names[0], names[1]+"."), "wrong FQDN: %q", names[0]) assert.Assert(t, !strings.HasSuffix(names[0], "."), "not expected root, got %q", names[0]) + + names = InstancePodDNSNames(ctx, instance, "override.cluster.local") + assert.Assert(t, len(names) > 0) + + assert.DeepEqual(t, names, []string{ + "cluster-name-id-0.cluster-pods.some-place.svc.override.cluster.local", + "cluster-name-id-0.cluster-pods.some-place.svc", + "cluster-name-id-0.cluster-pods.some-place", + "cluster-name-id-0.cluster-pods", + }) + + assert.Assert(t, len(names[0]) > len(names[1]), "expected FQDN first, got %q", names[0]) + assert.Assert(t, strings.HasPrefix(names[0], names[1]+"."), "wrong FQDN: %q", names[0]) + assert.Assert(t, !strings.HasSuffix(names[0], "."), "not expected root, got %q", names[0]) } func TestServiceDNSNames(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) + ctx, cancel := context.WithTimeout(t.Context(), time.Second) defer cancel() service := &corev1.Service{} service.Namespace = "baltia" service.Name = "the-primary" - names, err := ServiceDNSNames(ctx, service) + names, err := ServiceDNSNames(ctx, service, "") assert.NilError(t, err) assert.Assert(t, len(names) > 0) @@ -59,4 +73,19 @@ func TestServiceDNSNames(t *testing.T) { assert.Assert(t, len(names[0]) > len(names[1]), "expected FQDN first, got %q", names[0]) assert.Assert(t, strings.HasPrefix(names[0], names[1]+"."), "wrong FQDN: %q", names[0]) assert.Assert(t, !strings.HasSuffix(names[0], "."), "not expected root, got %q", names[0]) + + names, err = ServiceDNSNames(ctx, service, "override.cluster.local") + assert.NilError(t, err) + assert.Assert(t, len(names) > 0) + + assert.DeepEqual(t, names, []string{ + "the-primary.baltia.svc.override.cluster.local", + "the-primary.baltia.svc", + "the-primary.baltia", + "the-primary", + }) + + assert.Assert(t, len(names[0]) > len(names[1]), "expected FQDN first, got %q", names[0]) + assert.Assert(t, strings.HasPrefix(names[0], names[1]+"."), "wrong FQDN: %q", names[0]) + assert.Assert(t, !strings.HasSuffix(names[0], "."), "not expected root, got %q", names[0]) } diff --git a/internal/pgbackrest/config.go b/internal/pgbackrest/config.go index eecae059ac..18ecf847d7 100644 --- a/internal/pgbackrest/config.go +++ b/internal/pgbackrest/config.go @@ -68,8 +68,8 @@ const ( // pgbackrest_repo.conf is used by the pgBackRest repository pod func CreatePGBackRestConfigMapIntent(postgresCluster *v1beta1.PostgresCluster, repoHostName, configHash, serviceName, serviceNamespace string, - instanceNames []string) *corev1.ConfigMap { - + instanceNames []string, +) *corev1.ConfigMap { meta := naming.PGBackRestConfig(postgresCluster) meta.Annotations = naming.Merge( postgresCluster.Spec.Metadata.GetAnnotationsOrNil(), @@ -102,7 +102,7 @@ func CreatePGBackRestConfigMapIntent(postgresCluster *v1beta1.PostgresCluster, strconv.Itoa(postgresCluster.Spec.PostgresVersion), pgPort, postgresCluster.Spec.Backups.PGBackRest.Repos, postgresCluster.Spec.Backups.PGBackRest.Global, - ).String() + postgresCluster.Spec.ClusterServiceDNSSuffix).String() // PostgreSQL instances that have not rolled out expect to mount a server // config file. Always populate that file so those volumes stay valid and @@ -123,7 +123,7 @@ func CreatePGBackRestConfigMapIntent(postgresCluster *v1beta1.PostgresCluster, pgPort, instanceNames, postgresCluster.Spec.Backups.PGBackRest.Repos, postgresCluster.Spec.Backups.PGBackRest.Global, - ).String() + postgresCluster.Spec.ClusterServiceDNSSuffix).String() } cm.Data[ConfigHashKey] = configHash @@ -134,8 +134,8 @@ func CreatePGBackRestConfigMapIntent(postgresCluster *v1beta1.PostgresCluster, // MakePGBackrestLogDir creates the pgBackRest default log path directory used when a // dedicated repo host is configured. func MakePGBackrestLogDir(template *corev1.PodTemplateSpec, - cluster *v1beta1.PostgresCluster) { - + cluster *v1beta1.PostgresCluster, +) { var pgBackRestLogPath string for _, repo := range cluster.Spec.Backups.PGBackRest.Repos { if repo.Volume != nil { @@ -296,7 +296,6 @@ func RestoreCommand(pgdata, hugePagesSetting, fetchKeyCommand string, _ []*corev // ensures the configuration from the cluster being restored from is not utilized when bootstrapping a // new cluster, and the configuration for the new cluster is utilized instead. func DedicatedSnapshotVolumeRestoreCommand(pgdata string, args ...string) []string { - // The postmaster.pid file is removed, if it exists, before attempting a restore. // This allows the restore to be tried more than once without the causing an // error due to the presence of the file in subsequent attempts. @@ -332,13 +331,12 @@ func populatePGInstanceConfigurationMap( serviceName, serviceNamespace, repoHostName, pgdataDir, fetchKeyCommand, postgresVersion string, pgPort int32, repos []v1beta1.PGBackRestRepo, - globalConfig map[string]string, + globalConfig map[string]string, dnsSuffix string, ) iniSectionSet { - // TODO(cbandy): pass a FQDN in already. repoHostFQDN := repoHostName + "-0." + serviceName + "." + serviceNamespace + ".svc." + - naming.KubernetesClusterDomain(context.Background()) + naming.KubernetesClusterDomain(context.Background(), dnsSuffix) global := iniMultiSet{} stanza := iniMultiSet{} @@ -402,9 +400,8 @@ func populateRepoHostConfigurationMap( serviceName, serviceNamespace, pgdataDir, fetchKeyCommand, postgresVersion string, pgPort int32, pgHosts []string, repos []v1beta1.PGBackRestRepo, - globalConfig map[string]string, + globalConfig map[string]string, dnsSuffix string, ) iniSectionSet { - global := iniMultiSet{} stanza := iniMultiSet{} @@ -445,7 +442,7 @@ func populateRepoHostConfigurationMap( // TODO(cbandy): pass a FQDN in already. pgHostFQDN := pgHost + "-0." + serviceName + "." + serviceNamespace + ".svc." + - naming.KubernetesClusterDomain(context.Background()) + naming.KubernetesClusterDomain(context.Background(), dnsSuffix) stanza.Set(fmt.Sprintf("pg%d-host", i+1), pgHostFQDN) stanza.Set(fmt.Sprintf("pg%d-host-type", i+1), "tls") @@ -473,7 +470,6 @@ func populateRepoHostConfigurationMap( // getExternalRepoConfigs returns a map containing the configuration settings for an external // pgBackRest repository as defined in the PostgresCluster spec func getExternalRepoConfigs(repo v1beta1.PGBackRestRepo) map[string]string { - repoConfigs := make(map[string]string) if repo.Azure != nil { @@ -561,8 +557,10 @@ done ` export directory="$1" authority="$2" filename="$3"; export -f monitor;` + ` exec -a "$0" bash -ceu monitor` - return []string{"bash", "-ceu", "--", wrapper, name, - serverMountPath, certAuthorityAbsolutePath, serverConfigAbsolutePath} + return []string{ + "bash", "-ceu", "--", wrapper, name, + serverMountPath, certAuthorityAbsolutePath, serverConfigAbsolutePath, + } } // serverConfig returns the options needed to run the TLS server for cluster. diff --git a/internal/pgbackrest/config_test.go b/internal/pgbackrest/config_test.go index 766c6812f3..64d7e13000 100644 --- a/internal/pgbackrest/config_test.go +++ b/internal/pgbackrest/config_test.go @@ -35,7 +35,7 @@ func TestCreatePGBackRestConfigMapIntent(t *testing.T) { naming.LabelVersion: "2.3.0", } - domain := naming.KubernetesClusterDomain(context.Background()) + domain := naming.KubernetesClusterDomain(context.Background(), "") t.Run("NoVolumeRepo", func(t *testing.T) { cluster := cluster.DeepCopy() @@ -254,14 +254,16 @@ func TestMakePGBackrestLogDir(t *testing.T) { {Name: "test"}, }, Containers: []corev1.Container{ - {Name: "pgbackrest", + { + Name: "pgbackrest", Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("23m"), }, }, }, - }}} + }, + }} cluster := &v1beta1.PostgresCluster{ Spec: v1beta1.PostgresClusterSpec{ @@ -271,7 +273,8 @@ func TestMakePGBackrestLogDir(t *testing.T) { Image: "test-image", Repos: []v1beta1.PGBackRestRepo{ {Name: "repo1"}, - {Name: "repo2", + { + Name: "repo2", Volume: &v1beta1.RepoPVC{}, }, }, @@ -336,7 +339,8 @@ func TestRestoreCommand(t *testing.T) { pgdata := "/pgdata/pg13" opts := []string{ "--stanza=" + DefaultStanzaName, "--pg1-path=" + pgdata, - "--repo=1"} + "--repo=1", + } command := RestoreCommand(pgdata, "try", "", nil, strings.Join(opts, " ")) assert.DeepEqual(t, command[:3], []string{"bash", "-ceu", "--"}) @@ -375,7 +379,8 @@ func TestDedicatedSnapshotVolumeRestoreCommand(t *testing.T) { pgdata := "/pgdata/pg13" opts := []string{ "--stanza=" + DefaultStanzaName, "--pg1-path=" + pgdata, - "--repo=1"} + "--repo=1", + } command := DedicatedSnapshotVolumeRestoreCommand(pgdata, strings.Join(opts, " ")) assert.DeepEqual(t, command[:3], []string{"bash", "-ceu", "--"}) diff --git a/internal/pgbackrest/reconcile.go b/internal/pgbackrest/reconcile.go index e301618cc9..ce86813c6e 100644 --- a/internal/pgbackrest/reconcile.go +++ b/internal/pgbackrest/reconcile.go @@ -24,8 +24,8 @@ import ( // AddRepoVolumesToPod adds pgBackRest repository volumes to the provided Pod template spec, while // also adding associated volume mounts to the containers specified. func AddRepoVolumesToPod(postgresCluster *v1beta1.PostgresCluster, template *corev1.PodTemplateSpec, - repoPVCNames map[string]string, containerNames ...string) error { - + repoPVCNames map[string]string, containerNames ...string, +) error { for _, repo := range postgresCluster.Spec.Backups.PGBackRest.Repos { // we only care about repos created using PVCs if repo.Volume == nil { @@ -45,7 +45,8 @@ func AddRepoVolumesToPod(postgresCluster *v1beta1.PostgresCluster, template *cor Name: repo.Name, VolumeSource: corev1.VolumeSource{ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: repoVolName}, + ClaimName: repoVolName, + }, }, }) @@ -62,11 +63,10 @@ func AddRepoVolumesToPod(postgresCluster *v1beta1.PostgresCluster, template *cor "Unable to find init container %q when adding pgBackRest repo volumes", naming.ContainerPGBackRestLogDirInit) } - template.Spec.InitContainers[index].VolumeMounts = - append(template.Spec.InitContainers[index].VolumeMounts, corev1.VolumeMount{ - Name: repo.Name, - MountPath: "/pgbackrest/" + repo.Name, - }) + template.Spec.InitContainers[index].VolumeMounts = append(template.Spec.InitContainers[index].VolumeMounts, corev1.VolumeMount{ + Name: repo.Name, + MountPath: "/pgbackrest/" + repo.Name, + }) for _, name := range containerNames { var containerFound bool @@ -81,11 +81,10 @@ func AddRepoVolumesToPod(postgresCluster *v1beta1.PostgresCluster, template *cor return errors.Errorf("Unable to find container %q when adding pgBackRest repo volumes", name) } - template.Spec.Containers[index].VolumeMounts = - append(template.Spec.Containers[index].VolumeMounts, corev1.VolumeMount{ - Name: repo.Name, - MountPath: "/pgbackrest/" + repo.Name, - }) + template.Spec.Containers[index].VolumeMounts = append(template.Spec.Containers[index].VolumeMounts, corev1.VolumeMount{ + Name: repo.Name, + MountPath: "/pgbackrest/" + repo.Name, + }) } } @@ -551,7 +550,7 @@ func Secret(ctx context.Context, // The client verifies the "pg-host" or "repo-host" option it used is // present in the DNS names of the server certificate. leaf := &pki.LeafCertificate{} - dnsNames, err := naming.RepoHostPodDNSNames(ctx, inRepoHost) + dnsNames, err := naming.RepoHostPodDNSNames(ctx, inRepoHost, inCluster.Spec.ClusterServiceDNSSuffix) if err != nil { return errors.Wrap(err, "failed to resolve repo host pod DNS names") } diff --git a/internal/pgbouncer/reconcile.go b/internal/pgbouncer/reconcile.go index 8c0e92fdd6..d67910511f 100644 --- a/internal/pgbouncer/reconcile.go +++ b/internal/pgbouncer/reconcile.go @@ -73,7 +73,7 @@ func Secret(ctx context.Context, if inCluster.Spec.Proxy.PGBouncer.CustomTLSSecret == nil { leaf := &pki.LeafCertificate{} - dnsNames, err := naming.ServiceDNSNames(ctx, inService) + dnsNames, err := naming.ServiceDNSNames(ctx, inService, inCluster.Spec.ClusterServiceDNSSuffix) if err != nil { return errors.Wrap(err, "get service dns names") } diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index cbef05d958..8bb805a58d 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -174,6 +174,8 @@ type PerconaPGClusterSpec struct { // specified in `spec.users` across all databases associated with that user. // +optional AutoCreateUserSchema *bool `json:"autoCreateUserSchema,omitempty"` + + ClusterServiceDNSSuffix string `json:"clusterServiceDNSSuffix,omitempty"` } type StandbySpec struct { @@ -399,6 +401,7 @@ func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crun postgresCluster.Spec.TLSOnly = cr.Spec.TLSOnly postgresCluster.Spec.InitContainer = cr.Spec.InitContainer + postgresCluster.Spec.ClusterServiceDNSSuffix = cr.Spec.ClusterServiceDNSSuffix return postgresCluster, nil } diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 5bb7e58f4f..953045c873 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -191,6 +191,9 @@ type PostgresClusterSpec struct { // +optional InitContainer *InitContainerSpec `json:"initContainer,omitempty"` // K8SPG-613 + + // K8SPG-694 + ClusterServiceDNSSuffix string `json:"clusterServiceDNSSuffix,omitempty"` } type InitContainerSpec struct { From 1ec30a1810632bfc1d358fb9af9c19b2a9a67317 Mon Sep 17 00:00:00 2001 From: Mayank Shah Date: Mon, 16 Feb 2026 11:39:42 +0530 Subject: [PATCH 296/300] K8SPG-771: Offline snapshots (#1418) * wip: add fencing mechanism Signed-off-by: Mayank Shah * rename to suspended-instances Signed-off-by: Mayank Shah * add BackupSnapshots feature gate Signed-off-by: Mayank Shah * implement reconciler logic Signed-off-by: Mayank Shah * implement offline executor Signed-off-by: Mayank Shah * naming improvements Signed-off-by: Mayank Shah * add to scheme Signed-off-by: Mayank Shah * fix reconcile state Signed-off-by: Mayank Shah * bug fixes and improvements Signed-off-by: Mayank Shah * naming improvements and fixes Signed-off-by: Mayank Shah * ran make generate Signed-off-by: Mayank Shah * fix PGBackup field validations Signed-off-by: Mayank Shah * refactors and stability improvements Signed-off-by: Mayank Shah * update cr.yaml examples Signed-off-by: Mayank Shah * organize imports Signed-off-by: Mayank Shah * misspells Signed-off-by: Mayank Shah * improve fencing logic Signed-off-by: Mayank Shah * add extra validation Signed-off-by: Mayank Shah * improvements to suspended logic Signed-off-by: Mayank Shah * finalizer renaming Signed-off-by: Mayank Shah * remove enabled field Signed-off-by: Mayank Shah * implement snapshot schedules Signed-off-by: Mayank Shah * linting Signed-off-by: Mayank Shah * implement in-place restore Signed-off-by: Mayank Shah * update cr.yaml example Signed-off-by: Mayank Shah * linting Signed-off-by: Mayank Shah * no need to use configmap to track Signed-off-by: Mayank Shah * more improvements Signed-off-by: Mayank Shah * typo Signed-off-by: Mayank Shah * wip: PiTR Signed-off-by: Mayank Shah * support snapshots in WALWatcher Signed-off-by: Mayank Shah * bug fix Signed-off-by: Mayank Shah * update comments Signed-off-by: Mayank Shah * linting Signed-off-by: Mayank Shah * add PGO_FEATURE_GATES env variable to deploy Signed-off-by: Mayank Shah * add retry mechanism Signed-off-by: Mayank Shah * implement checkpointing Signed-off-by: Mayank Shah * add restore_command wrapper for snapshots Signed-off-by: Mayank Shah * add logic for creating snapshot signal file Signed-off-by: Mayank Shah * handle leader ep reconcile Signed-off-by: Mayank Shah * more improvements Signed-off-by: Mayank Shah * add e2e test Signed-off-by: Mayank Shah * wip: fix pitr Signed-off-by: Mayank Shah * in-place restore improvements Signed-off-by: Mayank Shah * update e2e test Signed-off-by: Mayank Shah * update test runs Signed-off-by: Mayank Shah * test fixes Signed-off-by: Mayank Shah * Update build/postgres-operator/restore_command.sh Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * support for WAL and Tablespace volumes Signed-off-by: Mayank Shah * fix tests Signed-off-by: Mayank Shah * workaround improvements Signed-off-by: Mayank Shah * update examples Signed-off-by: Mayank Shah * fix unit test Signed-off-by: Mayank Shah * remove unused code Signed-off-by: Mayank Shah * add unit test shouldFailSnapshot Signed-off-by: Mayank Shah * add unit tests for backup helpers Signed-off-by: Mayank Shah * linting Signed-off-by: Mayank Shah * cleanup unused code Signed-off-by: Mayank Shah * formatting Signed-off-by: Mayank Shah * code cleanup Signed-off-by: Mayank Shah * status improvements Signed-off-by: Mayank Shah * add more unit tests Signed-off-by: Mayank Shah * update e2e test assertions Signed-off-by: Mayank Shah * fix inconsistencies & address copilot comments Signed-off-by: Mayank Shah * remove sh prefix Signed-off-by: Mayank Shah * checkpoint timeout default to 5m Signed-off-by: Mayank Shah * linting Signed-off-by: Mayank Shah * POSIX-compliant script Signed-off-by: Mayank Shah * fix potential nil-ptr Signed-off-by: Mayank Shah * fix error messag Signed-off-by: Mayank Shah * fix invalid status update Signed-off-by: Mayank Shah * fix retries to get latest objecgt Signed-off-by: Mayank Shah * bugfix: restore reconcile can use incorrect volume spec Signed-off-by: Mayank Shah * add unit test Signed-off-by: Mayank Shah * fix linting suggestions Signed-off-by: Mayank Shah * prepare job should work when using separate wal volumes Signed-off-by: Mayank Shah * update unit tests Signed-off-by: Mayank Shah * spelling errors Signed-off-by: Mayank Shah * allow configuring checkpoint timeout Signed-off-by: Mayank Shah * fix restore wrapper Signed-off-by: Mayank Shah * consistent field naming Signed-off-by: Mayank Shah * fix retry loop Signed-off-by: Mayank Shah * no need to check PITR while unsuspending Signed-off-by: Mayank Shah * error message consistency Signed-off-by: Mayank Shah * remove duplicate code Signed-off-by: Mayank Shah * use fmt.Errorf Signed-off-by: Mayank Shah * catch potential nil error Signed-off-by: Mayank Shah * allow skipping checkpointing Signed-off-by: Mayank Shah * address copilot comments Signed-off-by: Mayank Shah * fix error message Signed-off-by: Mayank Shah --------- Signed-off-by: Mayank Shah Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../pgv2.percona.com_perconapgbackups.yaml | 34 +- .../pgv2.percona.com_perconapgclusters.yaml | 45 + .../pgv2.percona.com_perconapgrestores.yaml | 18 +- build/postgres-operator/Dockerfile | 1 + build/postgres-operator/init-entrypoint.sh | 1 + .../restore-command-wrapper.sh | 10 + cmd/postgres-operator/main.go | 3 + .../pgv2.percona.com_perconapgclusters.yaml | 97 +- config/manager/default/manager.yaml | 2 + deploy/backup.yaml | 1 + deploy/bundle.yaml | 99 +- deploy/cr.yaml | 4 + deploy/crd.yaml | 97 +- deploy/cw-bundle.yaml | 99 +- deploy/cw-operator.yaml | 2 + deploy/operator.yaml | 2 + deploy/restore.yaml | 1 + e2e-tests/functions | 1 + e2e-tests/run-pr.csv | 1 + e2e-tests/run-release.csv | 1 + .../00-assert.yaml | 24 + .../00-deploy-operator.yaml | 21 + .../01-assert.yaml | 106 ++ .../01-create-cluster.yaml | 14 + .../02-write-data.yaml | 17 + .../03-assert.yaml | 10 + .../03-read-from-primary.yaml | 13 + .../04-assert.yaml | 28 + .../04-create-backup-snapshot.yaml | 7 + .../05-assert.yaml | 41 + .../05-create-restore.yaml | 23 + .../06-assert.yaml | 11 + .../06-verify-restored-data.yaml | 13 + .../07-assert.yaml | 31 + .../07-create-backup-pgbackrest.yaml | 9 + .../08-assert.yaml | 28 + .../08-create-backup-snapshot.yaml | 7 + .../09-assert.yaml | 31 + .../09-create-restore-pitr.yaml | 47 + .../10-assert.yaml | 14 + .../10-verify-restored-data.yaml | 13 + .../11-assert.yaml | 106 ++ .../11-create-cluster-from-snapshot.yaml | 15 + .../12-assert.yaml | 11 + .../12-verify-restored-data.yaml | 13 + .../99-cleanup.yaml | 37 + .../controller/postgrescluster/controller.go | 12 +- .../controller/postgrescluster/instance.go | 10 +- .../postgrescluster/instance_test.go | 1 + .../controller/postgrescluster/postgres.go | 2 +- .../postgrescluster/snapshots_test.go | 8 +- internal/controller/runtime/pod_client.go | 4 +- internal/feature/features.go | 7 + internal/naming/labels.go | 3 + internal/naming/names.go | 8 + internal/pgbackrest/postgres.go | 3 +- internal/pgbackrest/postgres_test.go | 12 +- percona/controller/pgbackup/controller.go | 79 +- .../controller/pgbackup/snapshots/offline.go | 170 ++++ .../pgbackup/snapshots/reconcile.go | 494 ++++++++++ .../pgbackup/snapshots/reconcile_test.go | 493 ++++++++++ percona/controller/pgcluster/backup.go | 5 +- .../controller/pgcluster/controller_test.go | 2 +- percona/controller/pgcluster/restore.go | 3 +- percona/controller/pgcluster/schedule.go | 89 +- percona/controller/pgrestore/controller.go | 130 +-- .../pgrestore/snapshot/reconcile.go | 811 ++++++++++++++++ .../pgrestore/snapshot/reconcile_test.go | 910 ++++++++++++++++++ .../controller/pgrestore/utils/pgbackrest.go | 119 +++ percona/naming/annotations.go | 12 + percona/naming/finalizers.go | 8 +- percona/naming/kinds.go | 6 + percona/postgres/common.go | 83 ++ percona/watcher/wal.go | 7 +- percona/watcher/wal_test.go | 3 +- .../v2/perconapgbackup_types.go | 56 +- .../v2/perconapgbackup_types_test.go | 13 +- .../v2/perconapgcluster_types.go | 76 ++ .../v2/perconapgrestore_types.go | 33 +- .../v2/zz_generated.deepcopy.go | 127 +++ 80 files changed, 4815 insertions(+), 193 deletions(-) create mode 100644 build/postgres-operator/restore-command-wrapper.sh create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/00-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/01-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/01-create-cluster.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/02-write-data.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/03-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/03-read-from-primary.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/04-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/04-create-backup-snapshot.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/05-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/05-create-restore.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/06-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/06-verify-restored-data.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/07-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/07-create-backup-pgbackrest.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/08-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/08-create-backup-snapshot.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/09-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/09-create-restore-pitr.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/10-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/10-verify-restored-data.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/11-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/11-create-cluster-from-snapshot.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/12-assert.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/12-verify-restored-data.yaml create mode 100644 e2e-tests/tests/demand-backup-offline-snapshot/99-cleanup.yaml create mode 100644 percona/controller/pgbackup/snapshots/offline.go create mode 100644 percona/controller/pgbackup/snapshots/reconcile.go create mode 100644 percona/controller/pgbackup/snapshots/reconcile_test.go create mode 100644 percona/controller/pgrestore/snapshot/reconcile.go create mode 100644 percona/controller/pgrestore/snapshot/reconcile_test.go create mode 100644 percona/controller/pgrestore/utils/pgbackrest.go create mode 100644 percona/naming/kinds.go diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml index f9aaf1c422..8fe3ad1dd9 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgbackups.yaml @@ -70,6 +70,13 @@ spec: type: object spec: properties: + method: + default: pgbackrest + description: Method with which to perform the backup + enum: + - pgbackrest + - volumeSnapshot + type: string options: description: |- Command line options to include when running the pgBackRest backup command. @@ -80,14 +87,17 @@ spec: pgCluster: type: string repoName: - description: The name of the pgBackRest repo to run the backup command - against. + description: |- + The name of the pgBackRest repo to run the backup command against. + This is required when method is 'pgbackrest'. pattern: ^repo[1-4] type: string required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: repoName is required when method is 'pgbackrest' + rule: self.method == "volumeSnapshot" || has(self.repoName) status: properties: backupName: @@ -391,6 +401,24 @@ spec: required: - name type: object + snapshot: + properties: + dataVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing data volume + contents. + type: string + tablespaceVolumeSnapshotRefs: + additionalProperties: + type: string + description: |- + Names of the VolumeSnapshots containing tablespace volume contents. + Key is the name of the tablespace, value is the name of the VolumeSnapshot. + type: object + walVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing WAL volume + contents. + type: string + type: object state: type: string storageType: diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index e8859d08e9..0466c5a851 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -7110,6 +7110,51 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean + volumeSnapshots: + description: VolumeSnapshots configuration + properties: + className: + description: Name of the VolumeSnapshotClass to use. + type: string + mode: + default: offline + description: Mode of the VolumeSnapshot. + enum: + - offline + type: string + offlineConfig: + description: |- + Configuration for offline snapshot operations. + Ignored if mode is not offline. + properties: + checkpoint: + description: Checkpoint configuration for offline snapshot + operations. + properties: + enabled: + default: true + description: If set, a checkpoint is requested. + type: boolean + timeoutSeconds: + default: 300 + description: |- + Timeout for the checkpoint operation. + Ignored if checkpoint is not enabled. + format: int32 + minimum: 30 + type: integer + type: object + type: object + schedule: + description: |- + Defines the Cron schedule for a VolumeSnapshot. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + required: + - className + type: object type: object x-kubernetes-validations: - message: At least one repository must be configured when backups diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml index e1bc4d36b7..34a16e4f2f 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgrestores.yaml @@ -67,6 +67,9 @@ spec: pgCluster: description: The name of the PerconaPGCluster to perform restore. type: string + x-kubernetes-validations: + - message: pgCluster is an immutable field + rule: self == oldSelf repoName: description: |- The name of the pgBackRest repo within the source PostgresCluster that contains the backups @@ -74,10 +77,23 @@ spec: for the new PostgresCluster. pattern: ^repo[1-4] type: string + x-kubernetes-validations: + - message: repoName is an immutable field + rule: self == oldSelf + volumeSnapshotBackupName: + description: The name of the backup to perform in-place volume snapshot + restores from. + type: string + x-kubernetes-validations: + - message: volumeSnapshotBackupName is an immutable field + rule: self == oldSelf required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: either repoName or volumeSnapshotBackupName must be set + rule: ((has(self.repoName) && self.repoName != "") || (has(self.volumeSnapshotBackupName) + && self.volumeSnapshotBackupName != "")) status: properties: completed: diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index 2d0663c455..a159bf2710 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -69,6 +69,7 @@ COPY build/postgres-operator/init-entrypoint.sh /usr/local/bin COPY build/postgres-operator/postgres-entrypoint.sh /usr/local/bin COPY build/postgres-operator/postgres-liveness-check.sh /usr/local/bin COPY build/postgres-operator/postgres-readiness-check.sh /usr/local/bin +COPY build/postgres-operator/restore-command-wrapper.sh /usr/local/bin COPY hack/tools/queries /opt/crunchy/conf RUN chgrp -R 0 /opt/crunchy/conf && chmod -R g=u opt/crunchy/conf diff --git a/build/postgres-operator/init-entrypoint.sh b/build/postgres-operator/init-entrypoint.sh index 2fde1f02bf..3090212fbf 100755 --- a/build/postgres-operator/init-entrypoint.sh +++ b/build/postgres-operator/init-entrypoint.sh @@ -10,3 +10,4 @@ install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-entrypoi install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-liveness-check.sh" "${CRUNCHY_BINDIR}/bin/postgres-liveness-check.sh" install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-readiness-check.sh" "${CRUNCHY_BINDIR}/bin/postgres-readiness-check.sh" install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/relocate-extensions.sh" "${CRUNCHY_BINDIR}/bin/relocate-extensions.sh" +install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/restore-command-wrapper.sh" "${CRUNCHY_BINDIR}/bin/restore-command-wrapper.sh" diff --git a/build/postgres-operator/restore-command-wrapper.sh b/build/postgres-operator/restore-command-wrapper.sh new file mode 100644 index 0000000000..d2f24a206f --- /dev/null +++ b/build/postgres-operator/restore-command-wrapper.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +# When this marker exists (e.g. after a snapshot restore), skip all WAL recovery by +# exiting non-zero. Do not remove the file so every restore_command call is skipped. +if [ -f "${PGDATA}/skip-wal-recovery" ]; then + exit 1 +fi + +exec "$@" diff --git a/cmd/postgres-operator/main.go b/cmd/postgres-operator/main.go index 2decf235d8..130daba46c 100644 --- a/cmd/postgres-operator/main.go +++ b/cmd/postgres-operator/main.go @@ -14,6 +14,7 @@ import ( "time" "unicode" + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" "github.com/pkg/errors" "go.opentelemetry.io/otel" uzap "go.uber.org/zap" @@ -125,6 +126,8 @@ func main() { // Add Percona custom resource types to scheme assertNoError(v2.AddToScheme(mgr.GetScheme())) + assertNoError(volumesnapshotv1.AddToScheme(mgr.GetScheme())) + // add all PostgreSQL Operator controllers to the runtime manager err = addControllersToManager(ctx, mgr) assertNoError(err) diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 6fcdbc3bb8..836d8afba7 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -69,6 +69,13 @@ spec: type: object spec: properties: + method: + default: pgbackrest + description: Method with which to perform the backup + enum: + - pgbackrest + - volumeSnapshot + type: string options: description: |- Command line options to include when running the pgBackRest backup command. @@ -79,14 +86,17 @@ spec: pgCluster: type: string repoName: - description: The name of the pgBackRest repo to run the backup command - against. + description: |- + The name of the pgBackRest repo to run the backup command against. + This is required when method is 'pgbackrest'. pattern: ^repo[1-4] type: string required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: repoName is required when method is 'pgbackrest' + rule: self.method == "volumeSnapshot" || has(self.repoName) status: properties: backupName: @@ -390,6 +400,24 @@ spec: required: - name type: object + snapshot: + properties: + dataVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing data volume + contents. + type: string + tablespaceVolumeSnapshotRefs: + additionalProperties: + type: string + description: |- + Names of the VolumeSnapshots containing tablespace volume contents. + Key is the name of the tablespace, value is the name of the VolumeSnapshot. + type: object + walVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing WAL volume + contents. + type: string + type: object state: type: string storageType: @@ -7515,6 +7543,51 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean + volumeSnapshots: + description: VolumeSnapshots configuration + properties: + className: + description: Name of the VolumeSnapshotClass to use. + type: string + mode: + default: offline + description: Mode of the VolumeSnapshot. + enum: + - offline + type: string + offlineConfig: + description: |- + Configuration for offline snapshot operations. + Ignored if mode is not offline. + properties: + checkpoint: + description: Checkpoint configuration for offline snapshot + operations. + properties: + enabled: + default: true + description: If set, a checkpoint is requested. + type: boolean + timeoutSeconds: + default: 300 + description: |- + Timeout for the checkpoint operation. + Ignored if checkpoint is not enabled. + format: int32 + minimum: 30 + type: integer + type: object + type: object + schedule: + description: |- + Defines the Cron schedule for a VolumeSnapshot. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + required: + - className + type: object type: object x-kubernetes-validations: - message: At least one repository must be configured when backups @@ -21968,6 +22041,9 @@ spec: pgCluster: description: The name of the PerconaPGCluster to perform restore. type: string + x-kubernetes-validations: + - message: pgCluster is an immutable field + rule: self == oldSelf repoName: description: |- The name of the pgBackRest repo within the source PostgresCluster that contains the backups @@ -21975,10 +22051,23 @@ spec: for the new PostgresCluster. pattern: ^repo[1-4] type: string + x-kubernetes-validations: + - message: repoName is an immutable field + rule: self == oldSelf + volumeSnapshotBackupName: + description: The name of the backup to perform in-place volume snapshot + restores from. + type: string + x-kubernetes-validations: + - message: volumeSnapshotBackupName is an immutable field + rule: self == oldSelf required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: either repoName or volumeSnapshotBackupName must be set + rule: ((has(self.repoName) && self.repoName != "") || (has(self.volumeSnapshotBackupName) + && self.volumeSnapshotBackupName != "")) status: properties: completed: diff --git a/config/manager/default/manager.yaml b/config/manager/default/manager.yaml index d7a647692b..61d46218fa 100644 --- a/config/manager/default/manager.yaml +++ b/config/manager/default/manager.yaml @@ -39,6 +39,8 @@ spec: value: "1" - name: PPROF_BIND_ADDRESS value: "0" + - name: PGO_FEATURE_GATES + value: "" ports: - containerPort: 8080 name: metrics diff --git a/deploy/backup.yaml b/deploy/backup.yaml index 4ca1ee3725..34d87572fd 100644 --- a/deploy/backup.yaml +++ b/deploy/backup.yaml @@ -5,5 +5,6 @@ metadata: spec: pgCluster: cluster1 repoName: repo1 +# method: volumeSnapshot # options: # - --type=full diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index 87e3aa52fe..e090d721e8 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -364,6 +364,13 @@ spec: type: object spec: properties: + method: + default: pgbackrest + description: Method with which to perform the backup + enum: + - pgbackrest + - volumeSnapshot + type: string options: description: |- Command line options to include when running the pgBackRest backup command. @@ -374,14 +381,17 @@ spec: pgCluster: type: string repoName: - description: The name of the pgBackRest repo to run the backup command - against. + description: |- + The name of the pgBackRest repo to run the backup command against. + This is required when method is 'pgbackrest'. pattern: ^repo[1-4] type: string required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: repoName is required when method is 'pgbackrest' + rule: self.method == "volumeSnapshot" || has(self.repoName) status: properties: backupName: @@ -685,6 +695,24 @@ spec: required: - name type: object + snapshot: + properties: + dataVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing data volume + contents. + type: string + tablespaceVolumeSnapshotRefs: + additionalProperties: + type: string + description: |- + Names of the VolumeSnapshots containing tablespace volume contents. + Key is the name of the tablespace, value is the name of the VolumeSnapshot. + type: object + walVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing WAL volume + contents. + type: string + type: object state: type: string storageType: @@ -7812,6 +7840,51 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean + volumeSnapshots: + description: VolumeSnapshots configuration + properties: + className: + description: Name of the VolumeSnapshotClass to use. + type: string + mode: + default: offline + description: Mode of the VolumeSnapshot. + enum: + - offline + type: string + offlineConfig: + description: |- + Configuration for offline snapshot operations. + Ignored if mode is not offline. + properties: + checkpoint: + description: Checkpoint configuration for offline snapshot + operations. + properties: + enabled: + default: true + description: If set, a checkpoint is requested. + type: boolean + timeoutSeconds: + default: 300 + description: |- + Timeout for the checkpoint operation. + Ignored if checkpoint is not enabled. + format: int32 + minimum: 30 + type: integer + type: object + type: object + schedule: + description: |- + Defines the Cron schedule for a VolumeSnapshot. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + required: + - className + type: object type: object x-kubernetes-validations: - message: At least one repository must be configured when backups @@ -22267,6 +22340,9 @@ spec: pgCluster: description: The name of the PerconaPGCluster to perform restore. type: string + x-kubernetes-validations: + - message: pgCluster is an immutable field + rule: self == oldSelf repoName: description: |- The name of the pgBackRest repo within the source PostgresCluster that contains the backups @@ -22274,10 +22350,23 @@ spec: for the new PostgresCluster. pattern: ^repo[1-4] type: string + x-kubernetes-validations: + - message: repoName is an immutable field + rule: self == oldSelf + volumeSnapshotBackupName: + description: The name of the backup to perform in-place volume snapshot + restores from. + type: string + x-kubernetes-validations: + - message: volumeSnapshotBackupName is an immutable field + rule: self == oldSelf required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: either repoName or volumeSnapshotBackupName must be set + rule: ((has(self.repoName) && self.repoName != "") || (has(self.volumeSnapshotBackupName) + && self.volumeSnapshotBackupName != "")) status: properties: completed: @@ -54215,6 +54304,8 @@ spec: value: "1" - name: PPROF_BIND_ADDRESS value: "0" + - name: PGO_FEATURE_GATES + value: "" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/cr.yaml b/deploy/cr.yaml index 599a19c21b..83024e12f8 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -408,6 +408,10 @@ spec: backups: # trackLatestRestorableTime: true +# volumeSnapshots: +# mode: offline +# className: VOLUME-SNAPSHOT-CLASS +# schedule: "0 0 * * 6" pgbackrest: # metadata: # labels: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 0ae004e7cb..b839553102 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -364,6 +364,13 @@ spec: type: object spec: properties: + method: + default: pgbackrest + description: Method with which to perform the backup + enum: + - pgbackrest + - volumeSnapshot + type: string options: description: |- Command line options to include when running the pgBackRest backup command. @@ -374,14 +381,17 @@ spec: pgCluster: type: string repoName: - description: The name of the pgBackRest repo to run the backup command - against. + description: |- + The name of the pgBackRest repo to run the backup command against. + This is required when method is 'pgbackrest'. pattern: ^repo[1-4] type: string required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: repoName is required when method is 'pgbackrest' + rule: self.method == "volumeSnapshot" || has(self.repoName) status: properties: backupName: @@ -685,6 +695,24 @@ spec: required: - name type: object + snapshot: + properties: + dataVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing data volume + contents. + type: string + tablespaceVolumeSnapshotRefs: + additionalProperties: + type: string + description: |- + Names of the VolumeSnapshots containing tablespace volume contents. + Key is the name of the tablespace, value is the name of the VolumeSnapshot. + type: object + walVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing WAL volume + contents. + type: string + type: object state: type: string storageType: @@ -7812,6 +7840,51 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean + volumeSnapshots: + description: VolumeSnapshots configuration + properties: + className: + description: Name of the VolumeSnapshotClass to use. + type: string + mode: + default: offline + description: Mode of the VolumeSnapshot. + enum: + - offline + type: string + offlineConfig: + description: |- + Configuration for offline snapshot operations. + Ignored if mode is not offline. + properties: + checkpoint: + description: Checkpoint configuration for offline snapshot + operations. + properties: + enabled: + default: true + description: If set, a checkpoint is requested. + type: boolean + timeoutSeconds: + default: 300 + description: |- + Timeout for the checkpoint operation. + Ignored if checkpoint is not enabled. + format: int32 + minimum: 30 + type: integer + type: object + type: object + schedule: + description: |- + Defines the Cron schedule for a VolumeSnapshot. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + required: + - className + type: object type: object x-kubernetes-validations: - message: At least one repository must be configured when backups @@ -22267,6 +22340,9 @@ spec: pgCluster: description: The name of the PerconaPGCluster to perform restore. type: string + x-kubernetes-validations: + - message: pgCluster is an immutable field + rule: self == oldSelf repoName: description: |- The name of the pgBackRest repo within the source PostgresCluster that contains the backups @@ -22274,10 +22350,23 @@ spec: for the new PostgresCluster. pattern: ^repo[1-4] type: string + x-kubernetes-validations: + - message: repoName is an immutable field + rule: self == oldSelf + volumeSnapshotBackupName: + description: The name of the backup to perform in-place volume snapshot + restores from. + type: string + x-kubernetes-validations: + - message: volumeSnapshotBackupName is an immutable field + rule: self == oldSelf required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: either repoName or volumeSnapshotBackupName must be set + rule: ((has(self.repoName) && self.repoName != "") || (has(self.volumeSnapshotBackupName) + && self.volumeSnapshotBackupName != "")) status: properties: completed: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 11519a8144..620c9fba8a 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -364,6 +364,13 @@ spec: type: object spec: properties: + method: + default: pgbackrest + description: Method with which to perform the backup + enum: + - pgbackrest + - volumeSnapshot + type: string options: description: |- Command line options to include when running the pgBackRest backup command. @@ -374,14 +381,17 @@ spec: pgCluster: type: string repoName: - description: The name of the pgBackRest repo to run the backup command - against. + description: |- + The name of the pgBackRest repo to run the backup command against. + This is required when method is 'pgbackrest'. pattern: ^repo[1-4] type: string required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: repoName is required when method is 'pgbackrest' + rule: self.method == "volumeSnapshot" || has(self.repoName) status: properties: backupName: @@ -685,6 +695,24 @@ spec: required: - name type: object + snapshot: + properties: + dataVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing data volume + contents. + type: string + tablespaceVolumeSnapshotRefs: + additionalProperties: + type: string + description: |- + Names of the VolumeSnapshots containing tablespace volume contents. + Key is the name of the tablespace, value is the name of the VolumeSnapshot. + type: object + walVolumeSnapshotRef: + description: Name of the VolumeSnapshot containing WAL volume + contents. + type: string + type: object state: type: string storageType: @@ -7812,6 +7840,51 @@ spec: trackLatestRestorableTime: description: Enable tracking latest restorable time type: boolean + volumeSnapshots: + description: VolumeSnapshots configuration + properties: + className: + description: Name of the VolumeSnapshotClass to use. + type: string + mode: + default: offline + description: Mode of the VolumeSnapshot. + enum: + - offline + type: string + offlineConfig: + description: |- + Configuration for offline snapshot operations. + Ignored if mode is not offline. + properties: + checkpoint: + description: Checkpoint configuration for offline snapshot + operations. + properties: + enabled: + default: true + description: If set, a checkpoint is requested. + type: boolean + timeoutSeconds: + default: 300 + description: |- + Timeout for the checkpoint operation. + Ignored if checkpoint is not enabled. + format: int32 + minimum: 30 + type: integer + type: object + type: object + schedule: + description: |- + Defines the Cron schedule for a VolumeSnapshot. + Follows the standard Cron schedule syntax: + https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + minLength: 6 + type: string + required: + - className + type: object type: object x-kubernetes-validations: - message: At least one repository must be configured when backups @@ -22267,6 +22340,9 @@ spec: pgCluster: description: The name of the PerconaPGCluster to perform restore. type: string + x-kubernetes-validations: + - message: pgCluster is an immutable field + rule: self == oldSelf repoName: description: |- The name of the pgBackRest repo within the source PostgresCluster that contains the backups @@ -22274,10 +22350,23 @@ spec: for the new PostgresCluster. pattern: ^repo[1-4] type: string + x-kubernetes-validations: + - message: repoName is an immutable field + rule: self == oldSelf + volumeSnapshotBackupName: + description: The name of the backup to perform in-place volume snapshot + restores from. + type: string + x-kubernetes-validations: + - message: volumeSnapshotBackupName is an immutable field + rule: self == oldSelf required: - pgCluster - - repoName type: object + x-kubernetes-validations: + - message: either repoName or volumeSnapshotBackupName must be set + rule: ((has(self.repoName) && self.repoName != "") || (has(self.volumeSnapshotBackupName) + && self.volumeSnapshotBackupName != "")) status: properties: completed: @@ -54213,6 +54302,8 @@ spec: value: "1" - name: PPROF_BIND_ADDRESS value: "0" + - name: PGO_FEATURE_GATES + value: "" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/cw-operator.yaml b/deploy/cw-operator.yaml index 0a75a83fc4..25480469ad 100644 --- a/deploy/cw-operator.yaml +++ b/deploy/cw-operator.yaml @@ -46,6 +46,8 @@ spec: value: "1" - name: PPROF_BIND_ADDRESS value: "0" + - name: PGO_FEATURE_GATES + value: "" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 3595d64cfe..4cc6b05aae 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -49,6 +49,8 @@ spec: value: "1" - name: PPROF_BIND_ADDRESS value: "0" + - name: PGO_FEATURE_GATES + value: "" image: docker.io/perconalab/percona-postgresql-operator:main imagePullPolicy: Always livenessProbe: diff --git a/deploy/restore.yaml b/deploy/restore.yaml index e85f417e7c..411b1508e3 100644 --- a/deploy/restore.yaml +++ b/deploy/restore.yaml @@ -5,6 +5,7 @@ metadata: spec: pgCluster: cluster1 repoName: repo1 +# volumeSnapshotBackupName: backup1 # options: # - --type=time # - --target="2022-11-30 15:12:11+03" diff --git a/e2e-tests/functions b/e2e-tests/functions index 3a9e66ca9a..b35c245479 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -56,6 +56,7 @@ deploy_operator() { yq eval '.spec.template.spec.containers[0].image = "'${IMAGE}'"' "${DEPLOY_DIR}/${cw_prefix}operator.yaml" \ | yq eval '(.spec.template.spec.containers[] | select(.name=="operator") | .env[] | select(.name=="DISABLE_TELEMETRY") | .value) = "'${disable_telemetry}'"' - \ | yq eval '(.spec.template.spec.containers[] | select(.name=="operator") | .env[] | select(.name=="LOG_LEVEL") | .value) = "DEBUG"' - \ + | yq eval '(.spec.template.spec.containers[] | select(.name=="operator") | .env[] | select(.name=="PGO_FEATURE_GATES") | .value) = "'${PGO_FEATURE_GATES}'"' - \ | kubectl -n "${OPERATOR_NS:-$NAMESPACE}" apply -f - } diff --git a/e2e-tests/run-pr.csv b/e2e-tests/run-pr.csv index 5253b4a97f..beaf200b1a 100644 --- a/e2e-tests/run-pr.csv +++ b/e2e-tests/run-pr.csv @@ -5,6 +5,7 @@ custom-extensions custom-tls database-init-sql demand-backup +demand-backup-offline-snapshot finalizers init-deploy huge-pages diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 24f64d8906..1151e8b91b 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -5,6 +5,7 @@ custom-extensions custom-tls database-init-sql demand-backup +demand-backup-offline-snapshot finalizers init-deploy huge-pages diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/00-assert.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/00-deploy-operator.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/00-deploy-operator.yaml new file mode 100644 index 0000000000..50c7842282 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/00-deploy-operator.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + PGO_FEATURE_GATES="BackupSnapshots=true" deploy_operator + deploy_client + deploy_s3_secrets +--- +apiVersion: snapshot.storage.k8s.io/v1 +kind: VolumeSnapshotClass +metadata: + name: gke-snapshot-class +driver: pd.csi.storage.gke.io +deletionPolicy: Delete \ No newline at end of file diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/01-assert.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/01-assert.yaml new file mode 100644 index 0000000000..5dc595832c --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/01-assert.yaml @@ -0,0 +1,106 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 480 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: backup-snapshot + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: backup-snapshot + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: backup-snapshot-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: backup-snapshot + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: backup-snapshot + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: backup-snapshot + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: backup-snapshot + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: backup-snapshot + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repos: + - name: repo1 + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: backup-snapshot +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/01-create-cluster.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/01-create-cluster.yaml new file mode 100644 index 0000000000..157d0b2a2e --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/01-create-cluster.yaml @@ -0,0 +1,14 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr "backup-snapshot" ${RANDOM} \ + | yq '.spec.backups.volumeSnapshots.className="gke-snapshot-class"' \ + | yq '.spec.backups.volumeSnapshots.mode="offline"' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/02-write-data.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/02-write-data.yaml new file mode 100644 index 0000000000..14ba9bf5e1 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/02-write-data.yaml @@ -0,0 +1,17 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 60 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'CREATE DATABASE myapp; \c myapp \\\ CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY);' \ + "postgres:$(get_psql_user_pass backup-snapshot-pguser-postgres)@$(get_psql_user_host backup-snapshot-pguser-postgres)" + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ + "postgres:$(get_psql_user_pass backup-snapshot-pguser-postgres)@$(get_psql_user_host backup-snapshot-pguser-postgres)" diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/03-assert.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/03-assert.yaml new file mode 100644 index 0000000000..6848a5b79a --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/03-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 03-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/03-read-from-primary.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/03-read-from-primary.yaml new file mode 100644 index 0000000000..a58c96e1c3 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/03-read-from-primary.yaml @@ -0,0 +1,13 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass backup-snapshot-pguser-postgres)@$(get_psql_user_host backup-snapshot-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 03-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/04-assert.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/04-assert.yaml new file mode 100644 index 0000000000..3a662811e5 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/04-assert.yaml @@ -0,0 +1,28 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 560 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGBackup +metadata: + name: backup1 +spec: + pgCluster: backup-snapshot + method: volumeSnapshot +status: + state: Succeeded + snapshot: + dataVolumeSnapshotRef: backup1-pgdata +--- +kind: VolumeSnapshot +apiVersion: snapshot.storage.k8s.io/v1 +metadata: + name: backup1-pgdata + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + name: backup1 + controller: true + blockOwnerDeletion: true +status: + readyToUse: true \ No newline at end of file diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/04-create-backup-snapshot.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/04-create-backup-snapshot.yaml new file mode 100644 index 0000000000..ab38603357 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/04-create-backup-snapshot.yaml @@ -0,0 +1,7 @@ +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGBackup +metadata: + name: backup1 +spec: + pgCluster: backup-snapshot + method: volumeSnapshot diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/05-assert.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/05-assert.yaml new file mode 100644 index 0000000000..ec2c619a09 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/05-assert.yaml @@ -0,0 +1,41 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 600 +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + annotations: + pgv2.percona.com/snapshot-restore: restore1 + labels: + postgres-operator.crunchydata.com/cluster: backup-snapshot + postgres-operator.crunchydata.com/role: pgdata +spec: + dataSource: + apiGroup: snapshot.storage.k8s.io + kind: VolumeSnapshot + name: backup1-pgdata +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGRestore +metadata: + name: restore1 +status: + state: Succeeded +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: backup-snapshot +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready \ No newline at end of file diff --git a/e2e-tests/tests/demand-backup-offline-snapshot/05-create-restore.yaml b/e2e-tests/tests/demand-backup-offline-snapshot/05-create-restore.yaml new file mode 100644 index 0000000000..9b537d9f39 --- /dev/null +++ b/e2e-tests/tests/demand-backup-offline-snapshot/05-create-restore.yaml @@ -0,0 +1,23 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + '\c myapp \\\ TRUNCATE TABLE myApp' \ + "postgres:$(get_psql_user_pass backup-snapshot-pguser-postgres)@$(get_psql_user_host backup-snapshot-pguser-postgres)" + + cat < /pgdata/latest_commit_timestamp.txt; fi", }, ""), - "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, + "restore_command": `/opt/crunchy/bin/restore-command-wrapper.sh pgbackrest --stanza=db archive-get %f "%p"`, "track_commit_timestamp": "true", }) }) @@ -113,7 +113,7 @@ func TestPostgreSQLParameters(t *testing.T) { `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", }, ""), - "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, + "restore_command": `/opt/crunchy/bin/restore-command-wrapper.sh pgbackrest --stanza=db archive-get %f "%p"`, "track_commit_timestamp": "true", }) @@ -169,7 +169,7 @@ func TestPostgreSQLParameters(t *testing.T) { `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", }, ""), - "restore_command": `pgbackrest --stanza=db archive-get %f "%p" --repo=99`, + "restore_command": `/opt/crunchy/bin/restore-command-wrapper.sh pgbackrest --stanza=db archive-get %f "%p" --repo=99`, "track_commit_timestamp": "true", }) @@ -190,7 +190,7 @@ func TestPostgreSQLParameters(t *testing.T) { `grep -E "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{6}(Z|[\+\-][0-9]{2})$"); `, "if [ ! -z ${timestamp} ]; then echo ${timestamp} > /pgdata/latest_commit_timestamp.txt; fi", }, ""), - "restore_command": `pgbackrest --stanza=db archive-get %f "%p"`, + "restore_command": `/opt/crunchy/bin/restore-command-wrapper.sh pgbackrest --stanza=db archive-get %f "%p"`, "track_commit_timestamp": "true", }) }) diff --git a/percona/controller/pgbackup/controller.go b/percona/controller/pgbackup/controller.go index 2ef563ac6e..47db0cb35d 100644 --- a/percona/controller/pgbackup/controller.go +++ b/percona/controller/pgbackup/controller.go @@ -2,10 +2,12 @@ package pgbackup import ( "context" + "fmt" "path" "slices" "time" + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" "github.com/pkg/errors" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" @@ -14,6 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -23,10 +26,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/v2/internal/logging" "github.com/percona/percona-postgresql-operator/v2/internal/naming" "github.com/percona/percona-postgresql-operator/v2/percona/clientcmd" "github.com/percona/percona-postgresql-operator/v2/percona/controller" + "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgbackup/snapshots" pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" "github.com/percona/percona-postgresql-operator/v2/percona/pgbackrest" "github.com/percona/percona-postgresql-operator/v2/percona/watcher" @@ -43,16 +48,25 @@ var ErrBackupJobNotFound = errors.New("backup Job not found") // Reconciler holds resources for the PerconaPGBackup reconciler type PGBackupReconciler struct { - Client client.Client + Client client.Client + PodExec runtime.PodExecutor ExternalChan chan event.GenericEvent } // SetupWithManager adds the PerconaPGBackup controller to the provided runtime manager func (r *PGBackupReconciler) SetupWithManager(mgr manager.Manager) error { + if r.PodExec == nil { + var err error + r.PodExec, err = runtime.NewPodExecutor(mgr.GetConfig()) + if err != nil { + return err + } + } return (builder.ControllerManagedBy(mgr). For(&v2.PerconaPGBackup{}). WatchesRawSource(source.Channel(r.ExternalChan, &handler.EnqueueRequestForObject{})). + Owns(&volumesnapshotv1.VolumeSnapshot{}). Complete(r)) } @@ -80,6 +94,18 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re pgBackup.Default() + pgCluster := new(v2.PerconaPGCluster) + if err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: request.Namespace}, pgCluster); err != nil { + if !k8serrors.IsNotFound(err) { + return reconcile.Result{}, errors.Wrap(err, "get PerconaPGCluster") + } + pgCluster = nil + } + + if *pgBackup.Spec.Method == v2.BackupMethodVolumeSnapshot { + return snapshots.Reconcile(ctx, r.Client, r.PodExec, pgBackup, pgCluster) + } + if !pgBackup.DeletionTimestamp.IsZero() || pgBackup.Status.State == v2.BackupFailed { if _, err := runFinalizers(ctx, r.Client, pgBackup); err != nil { return reconcile.Result{}, errors.Wrap(err, "failed to run finalizers") @@ -93,12 +119,14 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re } } - pgCluster := new(v2.PerconaPGCluster) - if err := r.Client.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: request.Namespace}, pgCluster); err != nil { - if !k8serrors.IsNotFound(err) { - return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") + if ptr.Deref(pgBackup.Spec.RepoName, "") == "" { + if updErr := pgBackup.UpdateStatus(ctx, r.Client, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupFailed + bcp.Status.Error = "repoName is required when method is 'pgbackrest'" + }); updErr != nil { + return reconcile.Result{}, fmt.Errorf("failed to update backup status: %w", updErr) } - pgCluster = nil + return reconcile.Result{}, errors.New("'repoName' is required when method is 'pgbackrest'") } switch pgBackup.Status.State { @@ -152,10 +180,10 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re repo := getRepo(pgCluster, pgBackup) if repo == nil { - return reconcile.Result{}, errors.Errorf("%s repo not defined", pgBackup.Spec.RepoName) + return reconcile.Result{}, errors.Errorf("'%s' repo not defined", ptr.Deref(pgBackup.Spec.RepoName, "")) } - if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { + if err := pgBackup.UpdateStatus(ctx, r.Client, func(bcp *v2.PerconaPGBackup) { bcp.Status.Destination = getDestination(pgCluster, pgBackup) bcp.Status.Image = pgCluster.Spec.Backups.PGBackRest.Image bcp.Status.Repo = repo @@ -219,7 +247,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{}, errors.Wrap(err, "update PGBackup") } - if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { + if err := pgBackup.UpdateStatus(ctx, r.Client, func(bcp *v2.PerconaPGBackup) { bcp.Status.State = v2.BackupRunning bcp.Status.JobName = job.Name }); err != nil { @@ -233,7 +261,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re if err != nil { // If something has deleted the job even with the finalizer, we should fail the backup. if k8serrors.IsNotFound(err) { - if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { + if err := pgBackup.UpdateStatus(ctx, r.Client, func(bcp *v2.PerconaPGBackup) { bcp.Status.State = v2.BackupFailed }); err != nil { return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") @@ -265,7 +293,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{RequeueAfter: time.Second * 5}, nil } - if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { + if err := pgBackup.UpdateStatus(ctx, r.Client, func(bcp *v2.PerconaPGBackup) { bcp.Status.CompletedAt = job.Status.CompletionTime bcp.Status.State = status }); err != nil { @@ -301,7 +329,7 @@ func (r *PGBackupReconciler) Reconcile(ctx context.Context, request reconcile.Re if err == nil { log.Info("Got latest restorable timestamp", "timestamp", latestRestorableTime) - if err := updateStatus(ctx, r.Client, pgBackup, func(bcp *v2.PerconaPGBackup) { + if err := pgBackup.UpdateStatus(ctx, r.Client, func(bcp *v2.PerconaPGBackup) { bcp.Status.LatestRestorableTime.Time = latestRestorableTime }); err != nil { return reconcile.Result{}, errors.Wrap(err, "update PGBackup status") @@ -411,7 +439,7 @@ func getBackupInProgress(ctx context.Context, c client.Client, clusterName, ns s } func getRepo(pg *v2.PerconaPGCluster, pb *v2.PerconaPGBackup) *v1beta1.PGBackRestRepo { - repoName := pb.Spec.RepoName + repoName := ptr.Deref(pb.Spec.RepoName, "") for i, r := range pg.Spec.Backups.PGBackRest.Repos { if repoName == r.Name { return &pg.Spec.Backups.PGBackRest.Repos[i] @@ -444,7 +472,7 @@ func getDestination(pg *v2.PerconaPGCluster, pb *v2.PerconaPGBackup) string { } func updatePGBackrestInfo(ctx context.Context, c client.Client, pod *corev1.Pod, pgBackup *v2.PerconaPGBackup) error { - info, err := pgbackrest.GetInfo(ctx, pod, pgBackup.Spec.RepoName) + info, err := pgbackrest.GetInfo(ctx, pod, ptr.Deref(pgBackup.Spec.RepoName, "")) if err != nil { return errors.Wrap(err, "get pgBackRest info") } @@ -473,7 +501,7 @@ func updatePGBackrestInfo(ctx context.Context, c client.Client, pod *corev1.Pod, stanzaName = info.Name if pgBackup.Status.BackupName == "" { - if err := updateStatus(ctx, c, pgBackup, func(bcp *v2.PerconaPGBackup) { + if err := pgBackup.UpdateStatus(ctx, c, func(bcp *v2.PerconaPGBackup) { bcp.Status.BackupName = backup.Label bcp.Status.BackupType = backup.Type }); err != nil { @@ -481,7 +509,7 @@ func updatePGBackrestInfo(ctx context.Context, c client.Client, pod *corev1.Pod, } } - if err := pgbackrest.SetAnnotationsToBackup(ctx, pod, stanzaName, backup.Label, pgBackup.Spec.RepoName, map[string]string{ + if err := pgbackrest.SetAnnotationsToBackup(ctx, pod, stanzaName, backup.Label, ptr.Deref(pgBackup.Spec.RepoName, ""), map[string]string{ v2.PGBackrestAnnotationJobName: pgBackup.Status.JobName, }); err != nil { return errors.Wrap(err, "set annotations to backup") @@ -636,7 +664,7 @@ func startBackup(ctx context.Context, c client.Client, pb *v2.PerconaPGBackup) e pg.Spec.Backups.PGBackRest.Manual = new(v1beta1.PGBackRestManualBackup) } - pg.Spec.Backups.PGBackRest.Manual.RepoName = pb.Spec.RepoName + pg.Spec.Backups.PGBackRest.Manual.RepoName = ptr.Deref(pb.Spec.RepoName, "") pg.Spec.Backups.PGBackRest.Manual.Options = pb.Spec.Options return c.Update(ctx, pg) @@ -664,7 +692,7 @@ func findBackupJob(ctx context.Context, c client.Client, pb *v2.PerconaPGBackup) err := c.List(ctx, jobList, client.InNamespace(pb.Namespace), client.MatchingLabelsSelector{ - Selector: naming.PGBackRestBackupJobSelector(pb.Spec.PGCluster, pb.Spec.RepoName, naming.BackupManual), + Selector: naming.PGBackRestBackupJobSelector(pb.Spec.PGCluster, ptr.Deref(pb.Spec.RepoName, ""), naming.BackupManual), }) if err != nil { return nil, errors.Wrap(err, "get backup jobs") @@ -722,23 +750,10 @@ func failIfClusterIsNotReady(ctx context.Context, cl client.Client, pgCluster *v log.Info("Cluster is not ready for backup for too long. Setting it's state to Failed") - if err := updateStatus(ctx, cl, pgBackup, func(bcp *v2.PerconaPGBackup) { + if err := pgBackup.UpdateStatus(ctx, cl, func(bcp *v2.PerconaPGBackup) { bcp.Status.State = v2.BackupFailed }); err != nil { return errors.Wrap(err, "update PGBackup status") } return nil } - -func updateStatus(ctx context.Context, cl client.Client, pgBackup *v2.PerconaPGBackup, updateFunc func(bcp *v2.PerconaPGBackup)) error { - return retry.RetryOnConflict(retry.DefaultBackoff, func() error { - bcp := new(v2.PerconaPGBackup) - if err := cl.Get(ctx, client.ObjectKeyFromObject(pgBackup), bcp); err != nil { - return errors.Wrap(err, "get PGBackup") - } - - updateFunc(bcp) - - return cl.Status().Update(ctx, bcp) - }) -} diff --git a/percona/controller/pgbackup/snapshots/offline.go b/percona/controller/pgbackup/snapshots/offline.go new file mode 100644 index 0000000000..0bc9af76e7 --- /dev/null +++ b/percona/controller/pgbackup/snapshots/offline.go @@ -0,0 +1,170 @@ +package snapshots + +import ( + "context" + "fmt" + "io" + "time" + + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/internal/postgres" + perconaPG "github.com/percona/percona-postgresql-operator/v2/percona/postgres" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" +) + +const ( + waitTimeout = 5 * time.Minute + retryInterval = 3 * time.Second +) + +type offlineExec struct { + cl client.Client + cluster *v2.PerconaPGCluster + backup *v2.PerconaPGBackup + podExec runtime.PodExecutor + offlineConfig *v2.OfflineSnapshotConfig +} + +func newSnapshotConfig(pgCluster *v2.PerconaPGCluster) *v2.OfflineSnapshotConfig { + defaultConfig := v2.DefaultOfflineSnapshotConfig() + if pgCluster.Spec.Backups.VolumeSnapshots.OfflineConfig == nil { + return defaultConfig + } + + config := pgCluster.Spec.Backups.VolumeSnapshots.OfflineConfig.DeepCopy() + if config.Checkpoint == nil { + config.Checkpoint = defaultConfig.Checkpoint + } + return config +} + +func newOfflineExec(cl client.Client, podExec runtime.PodExecutor, pgCluster *v2.PerconaPGCluster, pgBackup *v2.PerconaPGBackup) *offlineExec { + return &offlineExec{ + cl: cl, + cluster: pgCluster, + backup: pgBackup, + podExec: podExec, + offlineConfig: newSnapshotConfig(pgCluster), + } +} + +func (e *offlineExec) prepare(ctx context.Context) (string, error) { + targetInstance, err := e.getBackupTarget(ctx) + if err != nil { + return "", errors.Wrap(err, "failed to get backup target pod") + } + + if err := e.checkpoint(ctx, targetInstance); err != nil { + return "", errors.Wrap(err, "failed to checkpoint instance") + } + + if err := e.suspendInstance(ctx, targetInstance); err != nil { + return "", errors.Wrap(err, "failed to suspend instance") + } + return targetInstance, nil +} + +func (e *offlineExec) checkpoint(ctx context.Context, instanceName string) error { + log := logging.FromContext(ctx) + defaults := v2.DefaultOfflineSnapshotConfig().Checkpoint + + skip := !ptr.Deref(e.offlineConfig.Checkpoint.Enabled, *defaults.Enabled) + if skip { + log.Info("Skipping checkpoint") + return nil + } + + exec := func(_ context.Context, stdin io.Reader, stdout, stderr io.Writer, command ...string) error { + return e.podExec(ctx, e.cluster.GetNamespace(), instanceName+"-0", naming.ContainerDatabase, stdin, stdout, stderr, command...) + } + + timeoutSeconds := ptr.Deref(e.offlineConfig.Checkpoint.TimeoutSeconds, *defaults.TimeoutSeconds) + stdout, stderr, err := postgres.Executor(exec). + ExecInDatabasesFromQuery(ctx, `SELECT pg_catalog.current_database()`, + `SET statement_timeout = :'timeout'; CHECKPOINT;`, + map[string]string{ + "timeout": fmt.Sprintf("%ds", timeoutSeconds), + "ON_ERROR_STOP": "on", // Abort when any one statement fails. + "QUIET": "on", // Do not print successful statements to stdout. + }) + if err != nil { + return errors.Wrap(err, "failed to execute checkpoint") + } + + if stderr != "" { + return fmt.Errorf("checkpoint failed: %s", stderr) + } + + log.Info("checkpoint executed", "stdout", stdout, "stderr", stderr) + return nil +} + +func (e *offlineExec) suspendInstance(ctx context.Context, instanceName string) error { + // Suspend and wait + instanceKey := client.ObjectKey{Namespace: e.cluster.GetNamespace(), Name: instanceName} + if err := wait.PollUntilContextTimeout(ctx, retryInterval, waitTimeout, true, func(ctx context.Context) (bool, error) { + return perconaPG.SuspendInstance(ctx, e.cl, instanceKey) + }); err != nil { + return errors.Wrap(err, "failed to wait for suspension") + } + return nil +} + +func (e *offlineExec) resumeInstance(ctx context.Context, instanceName string) error { + // unsuspend and wait + instanceKey := client.ObjectKey{Namespace: e.cluster.GetNamespace(), Name: instanceName} + if err := wait.PollUntilContextTimeout(ctx, retryInterval, waitTimeout, true, func(ctx context.Context) (bool, error) { + return perconaPG.UnsuspendInstance(ctx, e.cl, instanceKey) + }); err != nil { + return errors.Wrap(err, "failed to wait for unsuspend") + } + return nil +} + +func (e *offlineExec) finalize(ctx context.Context) error { + targetInstance, err := e.getBackupTarget(ctx) + if err != nil { + return errors.Wrap(err, "failed to get backup target") + } + + if err := e.resumeInstance(ctx, targetInstance); err != nil { + return errors.Wrap(err, "failed to resume instance") + } + return nil +} + +func (e *offlineExec) getBackupTarget(ctx context.Context) (string, error) { + // If we already determined it before, use it. + if name, ok := e.backup.GetAnnotations()[annotationBackupTarget]; ok && name != "" { + return name, nil + } + + log := logging.FromContext(ctx) + + // TODO: single node clusters do not have replicas. + // We should allow using a primary pod as the backup target. + // Since this is unsafe, we should let the user explicitly opt-in for this behavior. + replicas, err := perconaPG.GetReplicaPods(ctx, e.cl, e.cluster) + if err != nil { + return "", errors.Wrap(err, "failed to get replica pods") + } + if len(replicas) == 0 { + return "", errors.New("no replica pods found") + } + + targetPod := replicas[0] + instanceName := targetPod.GetLabels()[naming.LabelInstance] + if instanceName == "" { + return "", errors.New("cannot determine instance name from pod labels") + } + + log.Info("Selected backup target", "instance", instanceName) + return instanceName, nil +} diff --git a/percona/controller/pgbackup/snapshots/reconcile.go b/percona/controller/pgbackup/snapshots/reconcile.go new file mode 100644 index 0000000000..1a95f93492 --- /dev/null +++ b/percona/controller/pgbackup/snapshots/reconcile.go @@ -0,0 +1,494 @@ +package snapshots + +import ( + "context" + "fmt" + "time" + + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/util/retry" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" +) + +const ( + annotationBackupTarget = pNaming.PrefixPerconaPGV2 + "backup-target" + + defaultSnapshotErrorDeadline = 5 * time.Minute +) + +type snapshotExecutor interface { + // Prepare the cluster for performing a snapshot. + // Returns the name of the instance whose PVCs will be snapshotted. + prepare(ctx context.Context) (string, error) + // Complete the snapshot. + finalize(ctx context.Context) error +} + +type snapshotReconciler struct { + cl client.Client + log logging.Logger + cluster *v2.PerconaPGCluster + backup *v2.PerconaPGBackup + exec snapshotExecutor +} + +func newSnapshotReconciler( + cl client.Client, + log logging.Logger, + cluster *v2.PerconaPGCluster, + backup *v2.PerconaPGBackup, + exec snapshotExecutor, +) *snapshotReconciler { + return &snapshotReconciler{ + cl: cl, + log: log, + cluster: cluster, + backup: backup, + exec: exec, + } +} + +func newSnapshotExec( + cl client.Client, + podExec runtime.PodExecutor, + cluster *v2.PerconaPGCluster, + backup *v2.PerconaPGBackup, +) (snapshotExecutor, error) { + switch mode := cluster.Spec.Backups.VolumeSnapshots.Mode; mode { + case v2.VolumeSnapshotModeOffline: + return newOfflineExec(cl, podExec, cluster, backup), nil + default: + return nil, fmt.Errorf("invalid or unsupported volume snapshot mode: %s", mode) + } +} + +// Reconcile backup snapshot +func Reconcile( + ctx context.Context, + cl client.Client, + podExec runtime.PodExecutor, + pgBackup *v2.PerconaPGBackup, + pgCluster *v2.PerconaPGCluster, +) (reconcile.Result, error) { + if pgBackup == nil || pgCluster == nil { + return reconcile.Result{}, errors.New("PerconaPGBackup or PerconaPGCluster is nil or not found") + } + + log := logging.FromContext(ctx). + WithName("SnapshotReconciler"). + WithValues("backup", pgBackup.Name, "cluster", pgCluster.Name) + + // Do nothing if the feature is not enabled. + if !feature.Enabled(ctx, feature.BackupSnapshots) { + log.Info(fmt.Sprintf("Feature gate '%s' is not enabled, skipping snapshot reconciliation", feature.BackupSnapshots)) + return reconcile.Result{}, nil + } + + // Check if volume snapshots are enabled for this cluster. + if !pgCluster.Spec.Backups.IsVolumeSnapshotsEnabled() { + if updErr := pgBackup.UpdateStatus(ctx, cl, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupFailed + bcp.Status.Error = "Volume snapshots are not enabled for this cluster" + }); updErr != nil { + return reconcile.Result{}, fmt.Errorf("failed to update backup status: %w", updErr) + } + return reconcile.Result{}, nil + } + + exec, err := newSnapshotExec(cl, podExec, pgCluster, pgBackup) + if err != nil { + stsErr := fmt.Errorf("invalid or unsupported volume snapshot mode: %s", pgCluster.Spec.Backups.VolumeSnapshots.Mode) + if updErr := pgBackup.UpdateStatus(ctx, cl, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupFailed + bcp.Status.Error = stsErr.Error() + }); updErr != nil { + return reconcile.Result{}, fmt.Errorf("failed to update backup status: %w", updErr) + } + return reconcile.Result{}, stsErr + } + + r := newSnapshotReconciler(cl, log, pgCluster, pgBackup, exec) + return r.reconcile(ctx) +} + +func (r *snapshotReconciler) reconcile(ctx context.Context) (reconcile.Result, error) { + if !r.backup.GetDeletionTimestamp().IsZero() { + return reconcile.Result{}, r.complete(ctx) + } + + switch r.backup.Status.State { + case v2.BackupNew: + return r.reconcileNew(ctx) + case v2.BackupStarting: + return r.reconcileStarting(ctx) + case v2.BackupRunning: + return r.reconcileRunning(ctx) + case v2.BackupFailed, v2.BackupSucceeded: + return reconcile.Result{}, r.complete(ctx) + } + return reconcile.Result{}, nil +} + +func (r *snapshotReconciler) reconcileNew(ctx context.Context) (reconcile.Result, error) { + if r.cluster.Status.State != v2.AppStateReady { + r.log.Info("Waiting for cluster to be ready before creating snapshot") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + if updErr := r.backup.UpdateStatus(ctx, r.cl, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupStarting + }); updErr != nil { + return reconcile.Result{}, fmt.Errorf("failed to update backup status: %w", updErr) + } + r.log.Info("Snapshot is starting") + return reconcile.Result{}, nil +} + +func (r *snapshotReconciler) reconcileStarting(ctx context.Context) (reconcile.Result, error) { + if err := r.prepare(ctx); err != nil { + return reconcile.Result{}, err + } + + if updErr := r.backup.UpdateStatus(ctx, r.cl, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupRunning + bcp.Status.Snapshot = &v2.SnapshotStatus{} + }); updErr != nil { + return reconcile.Result{}, fmt.Errorf("failed to update backup status: %w", updErr) + } + r.log.Info("Snapshot is running") + return reconcile.Result{}, nil +} + +// +kubebuilder:rbac:groups=snapshot.storage.k8s.io,resources=volumesnapshots,verbs=get;list;watch;create +func (r *snapshotReconciler) reconcileRunning(ctx context.Context) (reconcile.Result, error) { + dataPVC, walPVC, tablespacePVCs, err := r.getTargetPVCs(ctx) + if err != nil { + return reconcile.Result{}, fmt.Errorf("failed to get target PVCs: %w", err) + } + + dataOk, err := r.reconcileDataSnapshot(ctx, dataPVC) + if err != nil { + return reconcile.Result{}, fmt.Errorf("failed to reconcile data snapshot: %w", err) + } + + walOk, err := r.reconcileWALSnapshot(ctx, walPVC) + if err != nil { + return reconcile.Result{}, fmt.Errorf("failed to reconcile WAL snapshot: %w", err) + } + + tablespaceOk, err := r.reconcileTablespaceSnapshot(ctx, tablespacePVCs) + if err != nil { + return reconcile.Result{}, fmt.Errorf("failed to reconcile tablespace snapshot: %w", err) + } + + if !dataOk || !walOk || !tablespaceOk { + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + if err := r.complete(ctx); err != nil { + return reconcile.Result{}, fmt.Errorf("failed to complete snapshot: %w", err) + } + + if err := r.backup.UpdateStatus(ctx, r.cl, func(bcp *v2.PerconaPGBackup) { + bcp.Status.State = v2.BackupSucceeded + bcp.Status.CompletedAt = ptr.To(metav1.Now()) + }); err != nil { + return reconcile.Result{}, fmt.Errorf("failed to update backup status: %w", err) + } + return reconcile.Result{}, nil +} + +func (r *snapshotReconciler) reconcileSnapshot(ctx context.Context, volumeSnapshot *volumesnapshotv1.VolumeSnapshot) (bool, error) { + created, err := r.ensureSnapshot(ctx, volumeSnapshot) + if err != nil { + return false, fmt.Errorf("failed to ensure snapshot: %w", err) + } + + log := r.log.WithValues("snapshot", volumeSnapshot.GetName()) + if created { + log.Info("Volume snapshot created successfully") + return false, nil // return back later to observe the status + } + + if err := r.cl.Get(ctx, client.ObjectKeyFromObject(volumeSnapshot), volumeSnapshot); err != nil { + return false, fmt.Errorf("failed to get volume snapshot: %w", err) + } + + switch { + // no status reported + case volumeSnapshot.Status == nil: + return false, nil + + // snapshot is complete and ready to be restored. + case ptr.Deref(volumeSnapshot.Status.ReadyToUse, false): + log.Info("Snapshot is complete and ready to be used") + return true, nil + + // error occurred while creating the snapshot. + case volumeSnapshot.Status.Error != nil: + // Some errors can be transient, so we should wait for a while before giving up. + message := ptr.Deref(volumeSnapshot.Status.Error.Message, "") + if !shouldFailSnapshot(volumeSnapshot) { + r.log.Info("Snapshot is in error state, but within deadline. Retrying.", "message", message) + return false, nil + } + + err := errors.New(message) + + log.Error(err, "Volume snapshot failed") + return false, err + + default: + return false, nil + } +} + +func (r *snapshotReconciler) generateSnapshotIntent( + snapshotRole, + sourcePVC string) (*volumesnapshotv1.VolumeSnapshot, error) { + name := r.backup.GetName() + "-" + snapshotRole + namespace := r.backup.GetNamespace() + volumeSnapshot := &volumesnapshotv1.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: volumesnapshotv1.VolumeSnapshotSpec{ + VolumeSnapshotClassName: ptr.To(r.cluster.Spec.Backups.VolumeSnapshots.ClassName), + Source: volumesnapshotv1.VolumeSnapshotSource{ + PersistentVolumeClaimName: &sourcePVC, + }, + }, + } + if err := controllerutil.SetControllerReference(r.backup, volumeSnapshot, r.cl.Scheme()); err != nil { + return nil, fmt.Errorf("failed to set owner reference on volume snapshot: %w", err) + } + return volumeSnapshot, nil +} + +func (r *snapshotReconciler) reconcileDataSnapshot(ctx context.Context, targetPVC string) (bool, error) { + volumeSnapshot, err := r.generateSnapshotIntent(naming.RolePostgresData, targetPVC) + if err != nil { + return false, fmt.Errorf("failed to generate snapshot intent: %w", err) + } + + ok, err := r.reconcileSnapshot(ctx, volumeSnapshot) + if err != nil { + return false, fmt.Errorf("failed to reconcile snapshot: %w", err) + } + + if err := r.backup.UpdateStatus(ctx, r.cl, func(bcp *v2.PerconaPGBackup) { + bcp.Status.Snapshot.DataVolumeSnapshotRef = ptr.To(volumeSnapshot.GetName()) + }); err != nil { + return false, fmt.Errorf("failed to update backup status: %w", err) + } + return ok, nil +} + +func (r *snapshotReconciler) reconcileWALSnapshot(ctx context.Context, targetPVC string) (bool, error) { + if targetPVC == "" { + return true, nil + } + + volumeSnapshot, err := r.generateSnapshotIntent(naming.RolePostgresWAL, targetPVC) + if err != nil { + return false, fmt.Errorf("failed to generate snapshot intent: %w", err) + } + + ok, err := r.reconcileSnapshot(ctx, volumeSnapshot) + if err != nil { + return false, fmt.Errorf("failed to reconcile snapshot: %w", err) + } + if err := r.backup.UpdateStatus(ctx, r.cl, func(bcp *v2.PerconaPGBackup) { + bcp.Status.Snapshot.WALVolumeSnapshotRef = ptr.To(volumeSnapshot.GetName()) + }); err != nil { + return false, fmt.Errorf("failed to update backup status: %w", err) + } + return ok, nil +} + +func (r *snapshotReconciler) reconcileTablespaceSnapshot(ctx context.Context, targetPVCs map[string]string) (bool, error) { + if len(targetPVCs) == 0 { + return true, nil + } + + done := true + for tsName, targetPVC := range targetPVCs { + role := tsName + "-" + naming.RoleTablespace + volumeSnapshot, err := r.generateSnapshotIntent(role, targetPVC) + if err != nil { + return false, fmt.Errorf("failed to generate snapshot intent: %w", err) + } + + ok, err := r.reconcileSnapshot(ctx, volumeSnapshot) + if err != nil { + return false, fmt.Errorf("failed to reconcile snapshot: %w", err) + } + + if err := r.backup.UpdateStatus(ctx, r.cl, func(bcp *v2.PerconaPGBackup) { + if bcp.Status.Snapshot.TablespaceVolumeSnapshotRefs == nil { + bcp.Status.Snapshot.TablespaceVolumeSnapshotRefs = make(map[string]string) + } + bcp.Status.Snapshot.TablespaceVolumeSnapshotRefs[tsName] = volumeSnapshot.GetName() + }); err != nil { + return false, fmt.Errorf("failed to update backup status: %w", err) + } + if !ok { + done = false + } + } + return done, nil +} + +func shouldFailSnapshot(volumeSnapshot *volumesnapshotv1.VolumeSnapshot) bool { + if volumeSnapshot.Status == nil || volumeSnapshot.Status.Error == nil || volumeSnapshot.Status.Error.Time.IsZero() { + return false + } + errAt := volumeSnapshot.Status.Error.Time + return !errAt.IsZero() && time.Now().After(errAt.Add(defaultSnapshotErrorDeadline)) +} + +func (r *snapshotReconciler) ensureSnapshot(ctx context.Context, volumeSnapshot *volumesnapshotv1.VolumeSnapshot) (bool, error) { + if err := r.cl.Create(ctx, volumeSnapshot); err != nil { + return false, client.IgnoreAlreadyExists(err) + } + return true, nil +} + +func (r *snapshotReconciler) getTargetPVCs(ctx context.Context) (string, string, map[string]string, error) { + targetInstance := r.backup.GetAnnotations()[annotationBackupTarget] + if targetInstance == "" { + return "", "", nil, fmt.Errorf("backup target instance is not found") + } + + dataPVC := "" + var dataVolumes corev1.PersistentVolumeClaimList + if err := r.cl.List(ctx, &dataVolumes, &client.ListOptions{ + Namespace: r.cluster.GetNamespace(), + LabelSelector: labels.SelectorFromSet(map[string]string{ + naming.LabelInstance: targetInstance, + naming.LabelRole: naming.RolePostgresData, + }), + }); err != nil { + return "", "", nil, fmt.Errorf("failed to list data volumes: %w", err) + } + if len(dataVolumes.Items) == 1 { + dataPVC = dataVolumes.Items[0].GetName() + } else { + return "", "", nil, fmt.Errorf("unexpected number of data volumes: %d", len(dataVolumes.Items)) + } + + walPVC := "" + var walVolumes corev1.PersistentVolumeClaimList + if err := r.cl.List(ctx, &walVolumes, &client.ListOptions{ + Namespace: r.cluster.GetNamespace(), + LabelSelector: labels.SelectorFromSet(map[string]string{ + naming.LabelInstance: targetInstance, + naming.LabelRole: naming.RolePostgresWAL, + }), + }); err != nil { + return "", "", nil, fmt.Errorf("failed to list WAL volumes: %w", err) + } + if len(walVolumes.Items) == 1 { + walPVC = walVolumes.Items[0].GetName() + } + + tablespacePVCs := make(map[string]string) + var tablespaceVolumes corev1.PersistentVolumeClaimList + if err := r.cl.List(ctx, &tablespaceVolumes, &client.ListOptions{ + Namespace: r.cluster.GetNamespace(), + LabelSelector: labels.SelectorFromSet(map[string]string{ + naming.LabelInstance: targetInstance, + naming.LabelRole: naming.RoleTablespace, + }), + }); err != nil { + return "", "", nil, fmt.Errorf("failed to list tablespace volumes: %w", err) + } + + for _, vol := range tablespaceVolumes.Items { + name := vol.GetLabels()[naming.LabelData] + tablespacePVCs[name] = vol.GetName() + } + + return dataPVC, walPVC, tablespacePVCs, nil +} + +func (r *snapshotReconciler) prepare(ctx context.Context) error { + // finalizer already present, prepare already completed + if controllerutil.ContainsFinalizer(r.backup, pNaming.FinalizerSnapshotInProgress) { + return nil + } + + // prepare the cluster + targetInstance, err := r.exec.prepare(ctx) + if err != nil { + return fmt.Errorf("failed to prepare for snapshot: %w", err) + } + + // Store the backup target instance for later retrieval. + orig := r.backup.DeepCopy() + annotations := r.backup.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + annotations[annotationBackupTarget] = targetInstance + r.backup.SetAnnotations(annotations) + if err := r.cl.Patch(ctx, r.backup.DeepCopy(), client.MergeFrom(orig)); err != nil { + return fmt.Errorf("failed to patch backup annotations: %w", err) + } + + // add finalizer + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + bcp := r.backup.DeepCopy() + if err := r.cl.Get(ctx, client.ObjectKeyFromObject(bcp), bcp); err != nil { + return err + } + orig := bcp.DeepCopy() + controllerutil.AddFinalizer(bcp, pNaming.FinalizerSnapshotInProgress) + return r.cl.Patch(ctx, bcp, client.MergeFrom(orig)) + }); err != nil { + return fmt.Errorf("failed to add backup finalizer: %w", err) + } + r.log.Info("Prepared for snapshot") + return nil +} + +func (r *snapshotReconciler) complete(ctx context.Context) error { + // already finalized + if !controllerutil.ContainsFinalizer(r.backup, pNaming.FinalizerSnapshotInProgress) { + return nil + } + + // run finalize + if err := r.exec.finalize(ctx); err != nil { + return fmt.Errorf("finalize failed: %w", err) + } + + // remove finalizer + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + bcp := r.backup.DeepCopy() + if err := r.cl.Get(ctx, client.ObjectKeyFromObject(bcp), bcp); err != nil { + return err + } + orig := bcp.DeepCopy() + controllerutil.RemoveFinalizer(bcp, pNaming.FinalizerSnapshotInProgress) + return r.cl.Patch(ctx, bcp, client.MergeFrom(orig)) + }); err != nil { + return fmt.Errorf("failed to remove finalizer: %w", err) + } + return nil +} diff --git a/percona/controller/pgbackup/snapshots/reconcile_test.go b/percona/controller/pgbackup/snapshots/reconcile_test.go new file mode 100644 index 0000000000..fd6ce033ec --- /dev/null +++ b/percona/controller/pgbackup/snapshots/reconcile_test.go @@ -0,0 +1,493 @@ +package snapshots + +import ( + "context" + "testing" + "time" + + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" +) + +func TestShouldFailSnapshot(t *testing.T) { + now := time.Now() + + tests := []struct { + name string + volumeSnapshot *volumesnapshotv1.VolumeSnapshot + wantFail bool + }{ + { + name: "Status.Error.Time is zero", + volumeSnapshot: &volumesnapshotv1.VolumeSnapshot{ + Status: &volumesnapshotv1.VolumeSnapshotStatus{ + Error: &volumesnapshotv1.VolumeSnapshotError{ + Time: ptr.To(metav1.Time{}), + }, + }, + }, + wantFail: false, + }, + { + name: "error within deadline", + volumeSnapshot: &volumesnapshotv1.VolumeSnapshot{ + Status: &volumesnapshotv1.VolumeSnapshotStatus{ + Error: &volumesnapshotv1.VolumeSnapshotError{ + Time: ptr.To(metav1.NewTime(now.Add(-1 * time.Minute))), // 1mins ago, within deadline + }, + }, + }, + wantFail: false, + }, + { + name: "error past deadline", + volumeSnapshot: &volumesnapshotv1.VolumeSnapshot{ + Status: &volumesnapshotv1.VolumeSnapshotStatus{ + Error: &volumesnapshotv1.VolumeSnapshotError{ + Time: ptr.To(metav1.NewTime(now.Add(-10 * time.Minute))), // 10 minutes ago (past 5min deadline) + }, + }, + }, + wantFail: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.wantFail, shouldFailSnapshot(tt.volumeSnapshot)) + }) + } +} + +func TestReconcileDataSnapshot(t *testing.T) { + ctx := context.Background() + ns := "test-ns" + backupName := "my-backup" + clusterName := "my-cluster" + pvcName := "data-pvc" + snapshotClassName := "test-snapshotclass" + + s := scheme.Scheme + require.NoError(t, corev1.AddToScheme(s)) + require.NoError(t, v2.AddToScheme(s)) + require.NoError(t, volumesnapshotv1.AddToScheme(s)) + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + Backups: v2.Backups{ + VolumeSnapshots: &v2.VolumeSnapshots{ + Mode: v2.VolumeSnapshotModeOffline, + ClassName: snapshotClassName, + }, + }, + }, + } + + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{}, + }, + } + + noopExec := &mockSnapshotExecutor{} + + t.Run("creates VolumeSnapshot and updates backup status", func(t *testing.T) { + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster). + WithStatusSubresource(backup). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileDataSnapshot(ctx, pvcName) + require.NoError(t, err) + assert.False(t, ok, "snapshot not ready yet") + + vsName := backupName + "-" + naming.RolePostgresData + vs := &volumesnapshotv1.VolumeSnapshot{} + require.NoError(t, cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: vsName}, vs)) + assert.Equal(t, snapshotClassName, ptr.Deref(vs.Spec.VolumeSnapshotClassName, "")) + assert.Equal(t, pvcName, ptr.Deref(vs.Spec.Source.PersistentVolumeClaimName, "")) + + updated := &v2.PerconaPGBackup{} + require.NoError(t, cl.Get(ctx, client.ObjectKeyFromObject(backup), updated)) + require.NotNil(t, updated.Status.Snapshot) + assert.Equal(t, vsName, *updated.Status.Snapshot.DataVolumeSnapshotRef) + }) + + t.Run("returns true when existing VolumeSnapshot is ReadyToUse", func(t *testing.T) { + vsName := backupName + "-" + naming.RolePostgresData + existingVS := &volumesnapshotv1.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{Name: vsName, Namespace: ns}, + Spec: volumesnapshotv1.VolumeSnapshotSpec{ + VolumeSnapshotClassName: ptr.To(snapshotClassName), + Source: volumesnapshotv1.VolumeSnapshotSource{ + PersistentVolumeClaimName: ptr.To(pvcName), + }, + }, + Status: &volumesnapshotv1.VolumeSnapshotStatus{ + ReadyToUse: ptr.To(true), + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster, existingVS). + WithStatusSubresource(backup, existingVS). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileDataSnapshot(ctx, pvcName) + require.NoError(t, err) + assert.True(t, ok, "snapshot ready") + }) +} + +func TestReconcileWALSnapshot(t *testing.T) { + ctx := context.Background() + ns := "test-ns" + backupName := "my-backup" + clusterName := "my-cluster" + walPVCName := "wal-pvc" + snapshotClassName := "test-snapshotclass" + + s := scheme.Scheme + require.NoError(t, corev1.AddToScheme(s)) + require.NoError(t, v2.AddToScheme(s)) + require.NoError(t, volumesnapshotv1.AddToScheme(s)) + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + Backups: v2.Backups{ + VolumeSnapshots: &v2.VolumeSnapshots{ + Mode: v2.VolumeSnapshotModeOffline, + ClassName: snapshotClassName, + }, + }, + }, + } + + noopExec := &mockSnapshotExecutor{} + + t.Run("returns true when target PVC is empty", func(t *testing.T) { + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{}, + }, + } + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster). + WithStatusSubresource(backup). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileWALSnapshot(ctx, "") + require.NoError(t, err) + assert.True(t, ok, "no WAL volume to snapshot") + }) + + t.Run("creates VolumeSnapshot and updates backup status", func(t *testing.T) { + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{}, + }, + } + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster). + WithStatusSubresource(backup). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileWALSnapshot(ctx, walPVCName) + require.NoError(t, err) + assert.False(t, ok, "snapshot not ready yet") + + vsName := backupName + "-" + naming.RolePostgresWAL + vs := &volumesnapshotv1.VolumeSnapshot{} + require.NoError(t, cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: vsName}, vs)) + assert.Equal(t, snapshotClassName, ptr.Deref(vs.Spec.VolumeSnapshotClassName, "")) + assert.Equal(t, walPVCName, ptr.Deref(vs.Spec.Source.PersistentVolumeClaimName, "")) + + updated := &v2.PerconaPGBackup{} + require.NoError(t, cl.Get(ctx, client.ObjectKeyFromObject(backup), updated)) + require.NotNil(t, updated.Status.Snapshot) + assert.Equal(t, vsName, *updated.Status.Snapshot.WALVolumeSnapshotRef) + }) + + t.Run("returns true when existing VolumeSnapshot is ReadyToUse", func(t *testing.T) { + vsName := backupName + "-" + naming.RolePostgresWAL + existingVS := &volumesnapshotv1.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{Name: vsName, Namespace: ns}, + Spec: volumesnapshotv1.VolumeSnapshotSpec{ + VolumeSnapshotClassName: ptr.To(snapshotClassName), + Source: volumesnapshotv1.VolumeSnapshotSource{ + PersistentVolumeClaimName: ptr.To(walPVCName), + }, + }, + Status: &volumesnapshotv1.VolumeSnapshotStatus{ + ReadyToUse: ptr.To(true), + }, + } + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{}, + }, + } + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster, existingVS). + WithStatusSubresource(backup, existingVS). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileWALSnapshot(ctx, walPVCName) + require.NoError(t, err) + assert.True(t, ok, "snapshot ready") + }) +} + +func TestReconcileTablespaceSnapshot(t *testing.T) { + ctx := context.Background() + ns := "test-ns" + backupName := "my-backup" + clusterName := "my-cluster" + snapshotClassName := "test-snapshotclass" + ts1Name, ts2Name := "ts1", "ts2" + ts1PVC, ts2PVC := "pvc-ts1", "pvc-ts2" + + s := scheme.Scheme + require.NoError(t, corev1.AddToScheme(s)) + require.NoError(t, v2.AddToScheme(s)) + require.NoError(t, volumesnapshotv1.AddToScheme(s)) + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + Backups: v2.Backups{ + VolumeSnapshots: &v2.VolumeSnapshots{ + Mode: v2.VolumeSnapshotModeOffline, + ClassName: snapshotClassName, + }, + }, + }, + } + + noopExec := &mockSnapshotExecutor{} + + t.Run("returns true when TablespaceVolumes is empty", func(t *testing.T) { + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{}, + }, + } + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster). + WithStatusSubresource(backup). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileTablespaceSnapshot(ctx, nil) + require.NoError(t, err) + assert.True(t, ok, "no tablespace volumes to snapshot") + }) + + t.Run("creates VolumeSnapshots and updates backup status", func(t *testing.T) { + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{}, + }, + } + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster). + WithStatusSubresource(backup). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileTablespaceSnapshot(ctx, map[string]string{ + ts1Name: ts1PVC, + ts2Name: ts2PVC, + }) + require.NoError(t, err) + assert.False(t, ok, "snapshots not ready yet") + + for _, tc := range []struct { + tsName string + pvc string + }{ + {ts1Name, ts1PVC}, + {ts2Name, ts2PVC}, + } { + vsName := backupName + "-" + tc.tsName + "-" + naming.RoleTablespace + vs := &volumesnapshotv1.VolumeSnapshot{} + require.NoError(t, cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: vsName}, vs)) + assert.Equal(t, snapshotClassName, ptr.Deref(vs.Spec.VolumeSnapshotClassName, "")) + assert.Equal(t, tc.pvc, ptr.Deref(vs.Spec.Source.PersistentVolumeClaimName, "")) + } + + updated := &v2.PerconaPGBackup{} + require.NoError(t, cl.Get(ctx, client.ObjectKeyFromObject(backup), updated)) + require.NotNil(t, updated.Status.Snapshot) + assert.Equal(t, backupName+"-"+ts1Name+"-"+naming.RoleTablespace, updated.Status.Snapshot.TablespaceVolumeSnapshotRefs[ts1Name]) + assert.Equal(t, backupName+"-"+ts2Name+"-"+naming.RoleTablespace, updated.Status.Snapshot.TablespaceVolumeSnapshotRefs[ts2Name]) + }) + + t.Run("returns true when all existing VolumeSnapshots are ReadyToUse", func(t *testing.T) { + vs1Name := backupName + "-" + ts1Name + "-" + naming.RoleTablespace + vs2Name := backupName + "-" + ts2Name + "-" + naming.RoleTablespace + existingVS1 := &volumesnapshotv1.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{Name: vs1Name, Namespace: ns}, + Spec: volumesnapshotv1.VolumeSnapshotSpec{ + VolumeSnapshotClassName: ptr.To(snapshotClassName), + Source: volumesnapshotv1.VolumeSnapshotSource{ + PersistentVolumeClaimName: ptr.To(ts1PVC), + }, + }, + Status: &volumesnapshotv1.VolumeSnapshotStatus{ReadyToUse: ptr.To(true)}, + } + existingVS2 := &volumesnapshotv1.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{Name: vs2Name, Namespace: ns}, + Spec: volumesnapshotv1.VolumeSnapshotSpec{ + VolumeSnapshotClassName: ptr.To(snapshotClassName), + Source: volumesnapshotv1.VolumeSnapshotSource{ + PersistentVolumeClaimName: ptr.To(ts2PVC), + }, + }, + Status: &volumesnapshotv1.VolumeSnapshotStatus{ReadyToUse: ptr.To(true)}, + } + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{}, + }, + } + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup.DeepCopy(), cluster, existingVS1, existingVS2). + WithStatusSubresource(backup, existingVS1, existingVS2). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, noopExec) + ok, err := r.reconcileTablespaceSnapshot(ctx, map[string]string{ + ts1Name: ts1PVC, + ts2Name: ts2PVC, + }) + require.NoError(t, err) + assert.True(t, ok, "all tablespace snapshots ready") + }) +} + +func TestGenerateSnapshotIntent(t *testing.T) { + ns := "test-ns" + backupName := "my-backup" + clusterName := "my-cluster" + snapshotClassName := "test-snapshotclass" + + s := scheme.Scheme + require.NoError(t, corev1.AddToScheme(s)) + require.NoError(t, v2.AddToScheme(s)) + require.NoError(t, volumesnapshotv1.AddToScheme(s)) + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + Backups: v2.Backups{ + VolumeSnapshots: &v2.VolumeSnapshots{ + Mode: v2.VolumeSnapshotModeOffline, + ClassName: snapshotClassName, + }, + }, + }, + } + + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns, UID: "backup-uid"}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(backup, cluster). + Build() + + r := newSnapshotReconciler(cl, logging.Discard(), cluster, backup, &mockSnapshotExecutor{}) + + tests := []struct { + name string + snapshotRole string + sourcePVC string + wantName string + }{ + { + name: "data volume", + snapshotRole: naming.RolePostgresData, + sourcePVC: "data-pvc", + wantName: backupName + "-" + naming.RolePostgresData, + }, + { + name: "WAL volume", + snapshotRole: naming.RolePostgresWAL, + sourcePVC: "wal-pvc", + wantName: backupName + "-" + naming.RolePostgresWAL, + }, + { + name: "tablespace volume", + snapshotRole: "ts1-" + naming.RoleTablespace, + sourcePVC: "pvc-ts1", + wantName: backupName + "-" + "ts1-" + naming.RoleTablespace, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + vs, err := r.generateSnapshotIntent(tt.snapshotRole, tt.sourcePVC) + require.NoError(t, err) + require.NotNil(t, vs) + + assert.Equal(t, tt.wantName, vs.Name) + assert.Equal(t, ns, vs.Namespace) + assert.Equal(t, snapshotClassName, ptr.Deref(vs.Spec.VolumeSnapshotClassName, "")) + assert.Equal(t, tt.sourcePVC, ptr.Deref(vs.Spec.Source.PersistentVolumeClaimName, "")) + + // Owner reference should be set to the backup + require.NotEmpty(t, vs.OwnerReferences, "expected owner reference to be set") + assert.Equal(t, backupName, vs.OwnerReferences[0].Name) + assert.Equal(t, "pgv2.percona.com/v2", vs.OwnerReferences[0].APIVersion) + assert.Equal(t, "PerconaPGBackup", vs.OwnerReferences[0].Kind) + }) + } +} + +// mockSnapshotExecutor is a no-op snapshotExecutor for tests. +type mockSnapshotExecutor struct{} + +func (m *mockSnapshotExecutor) prepare(ctx context.Context) (string, error) { return "instance-0", nil } +func (m *mockSnapshotExecutor) finalize(ctx context.Context) error { return nil } diff --git a/percona/controller/pgcluster/backup.go b/percona/controller/pgcluster/backup.go index 06c680e258..b1aea84bc2 100644 --- a/percona/controller/pgcluster/backup.go +++ b/percona/controller/pgcluster/backup.go @@ -10,6 +10,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/util/retry" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -166,7 +167,7 @@ func reconcileBackupJob(ctx context.Context, cl client.Client, cr *v2.PerconaPGC }, Spec: v2.PerconaPGBackupSpec{ PGCluster: cr.Name, - RepoName: repoName, + RepoName: ptr.To(repoName), }, } if cr.CompareVersion("2.6.0") >= 0 && cr.Spec.Metadata != nil { @@ -227,7 +228,7 @@ func listPGBackups(ctx context.Context, cl client.Reader, cr *v2.PerconaPGCluste // we should not filter by label, because the user can create the resource without the label list := []v2.PerconaPGBackup{} for _, pgBackup := range pbList.Items { - if pgBackup.Spec.PGCluster != cr.Name || pgBackup.Spec.RepoName != repoName { + if pgBackup.Spec.PGCluster != cr.Name || ptr.Deref(pgBackup.Spec.RepoName, "") != repoName { continue } list = append(list, pgBackup) diff --git a/percona/controller/pgcluster/controller_test.go b/percona/controller/pgcluster/controller_test.go index 30de7aece2..b5427d3391 100644 --- a/percona/controller/pgcluster/controller_test.go +++ b/percona/controller/pgcluster/controller_test.go @@ -862,7 +862,7 @@ var _ = Describe("Pause with backup", Ordered, func() { }, Spec: v2.PerconaPGBackupSpec{ PGCluster: crName, - RepoName: "repo1", + RepoName: ptr.To("repo1"), }, } diff --git a/percona/controller/pgcluster/restore.go b/percona/controller/pgcluster/restore.go index d941aa05b5..d5cc2fdfb1 100644 --- a/percona/controller/pgcluster/restore.go +++ b/percona/controller/pgcluster/restore.go @@ -5,6 +5,7 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "github.com/percona/percona-postgresql-operator/v2/internal/naming" pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" @@ -39,7 +40,7 @@ func (r *PGClusterReconciler) createBootstrapRestoreObject(ctx context.Context, }, Spec: v2.PerconaPGRestoreSpec{ PGCluster: cr.Name, - RepoName: repoName, + RepoName: ptr.To(repoName), }, } if cr.CompareVersion("2.6.0") >= 0 && cr.Spec.Metadata != nil { diff --git a/percona/controller/pgcluster/schedule.go b/percona/controller/pgcluster/schedule.go index ad5d65412f..125c5921de 100644 --- a/percona/controller/pgcluster/schedule.go +++ b/percona/controller/pgcluster/schedule.go @@ -9,8 +9,10 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" "github.com/percona/percona-postgresql-operator/v2/internal/controller/postgrescluster" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" "github.com/percona/percona-postgresql-operator/v2/internal/logging" "github.com/percona/percona-postgresql-operator/v2/internal/naming" pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" @@ -28,6 +30,12 @@ func (r *PGClusterReconciler) reconcileScheduledBackups(ctx context.Context, cr } } } + + if cr.Spec.Backups.IsVolumeSnapshotsEnabled() && feature.Enabled(ctx, feature.BackupSnapshots) { + if err := r.reconcileScheduledSnapshots(ctx, cr, cr.Spec.Backups.VolumeSnapshots.Schedule); err != nil { + return errors.Wrapf(err, "failed to reconcile scheduled snapshots") + } + } return nil } @@ -120,7 +128,7 @@ func (r *PGClusterReconciler) createScheduledBackup(log logr.Logger, backupName, }, Spec: v2.PerconaPGBackupSpec{ PGCluster: cr.Name, - RepoName: repoName, + RepoName: ptr.To(repoName), Options: []string{"--type=" + backupType}, }, } @@ -136,3 +144,82 @@ func (r *PGClusterReconciler) createScheduledBackup(log logr.Logger, backupName, } return nil } + +func (r *PGClusterReconciler) createScheduledSnapshotFunc(log logr.Logger, backupName, namespace, clusterName string) func() { + return func() { + if err := r.createScheduledSnapshot(log, backupName, namespace, clusterName); err != nil { + log.Error(err, "failed to create a scheduled snapshot") + } + } +} + +func (r *PGClusterReconciler) createScheduledSnapshot(log logr.Logger, backupName, namespace, clusterName string) error { + ctx := context.Background() + + cr := &v2.PerconaPGCluster{} + if err := r.Client.Get(ctx, types.NamespacedName{ + Namespace: namespace, + Name: clusterName, + }, cr); err != nil { + if k8serrors.IsNotFound(err) { + log.Info("cluster is not found, deleting the job", "name", backupName, "cluster", cr.Name, "namespace", cr.Namespace) + + r.Cron.DeleteBackupJob(backupName, namespace) + return nil + } + return err + } + if cr.Status.State != v2.AppStateReady { + log.Info("Cluster is not ready. Can't start scheduled snapshot") + return nil + } + + pb := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: backupName + "-", + Namespace: namespace, + }, + Spec: v2.PerconaPGBackupSpec{ + PGCluster: cr.Name, + Method: ptr.To(v2.BackupMethodVolumeSnapshot), + }, + } + + if cr.Spec.Metadata != nil { + pb.Annotations = cr.Spec.Metadata.Annotations + pb.Labels = cr.Spec.Metadata.Labels + } + + err := r.Client.Create(ctx, pb) + if err != nil { + return errors.Wrapf(err, "failed to create PerconaPGBackup %s", backupName) + } + return nil +} + +func (r *PGClusterReconciler) reconcileScheduledSnapshots( + ctx context.Context, + cr *v2.PerconaPGCluster, + schedule *string) error { + log := logging.FromContext(ctx) + + name := naming.VolumeSnapshotCronJob(&v1beta1.PostgresCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: cr.Name, + Namespace: cr.Namespace, + }}) + + if schedule == nil || *schedule == "" { + r.Cron.DeleteBackupJob(name.Name, name.Namespace) + return nil + } + + createBackupFunc := r.createScheduledSnapshotFunc(log, name.Name, cr.Namespace, cr.Name) + + if err := r.Cron.ApplyBackupJob(name.Name, name.Namespace, *schedule, createBackupFunc); err != nil { + log.Error(err, "failed to create a cron for a scheduled snapshot job") + return err + } + + return nil +} diff --git a/percona/controller/pgrestore/controller.go b/percona/controller/pgrestore/controller.go index 0061744463..233bff1de7 100644 --- a/percona/controller/pgrestore/controller.go +++ b/percona/controller/pgrestore/controller.go @@ -16,12 +16,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/reconcile" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" "github.com/percona/percona-postgresql-operator/v2/internal/logging" - "github.com/percona/percona-postgresql-operator/v2/internal/naming" "github.com/percona/percona-postgresql-operator/v2/percona/controller" + "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgrestore/snapshot" + restoreutils "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgrestore/utils" pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" - "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) const ( @@ -35,10 +36,18 @@ type PGRestoreReconciler struct { Owner client.FieldOwner Recorder record.EventRecorder Tracer trace.Tracer + PodExec runtime.PodExecutor } // SetupWithManager adds the perconapgrestore controller to the provided runtime manager func (r *PGRestoreReconciler) SetupWithManager(mgr manager.Manager) error { + if r.PodExec == nil { + var err error + r.PodExec, err = runtime.NewPodExecutor(mgr.GetConfig()) + if err != nil { + return err + } + } return builder.ControllerManagedBy(mgr).For(&v2.PerconaPGRestore{}).Complete(r) } @@ -62,6 +71,17 @@ func (r *PGRestoreReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, err } + pgCluster := &v2.PerconaPGCluster{} + err := r.Client.Get(ctx, types.NamespacedName{Name: pgRestore.Spec.PGCluster, Namespace: request.Namespace}, pgCluster) + if err != nil { + return reconcile.Result{}, errors.Wrap(err, "get PerconaPGCluster") + } + + if pgRestore.Spec.VolumeSnapshotBackupName != "" { + // Delegate to snapshot restore reconciliation + return snapshot.Reconcile(ctx, r.Client, r.PodExec, pgCluster, pgRestore) + } + if pgRestore.DeletionTimestamp != nil { if err := runFinalizers(ctx, r.Client, pgRestore); err != nil { return reconcile.Result{}, errors.Wrap(err, "failed to run finalizers") @@ -73,11 +93,7 @@ func (r *PGRestoreReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, nil } - pgCluster := &v2.PerconaPGCluster{} - err := r.Client.Get(ctx, types.NamespacedName{Name: pgRestore.Spec.PGCluster, Namespace: request.Namespace}, pgCluster) - if err != nil { - return reconcile.Result{}, errors.Wrap(err, "get PostgresCluster") - } + restorer := restoreutils.NewPGBackRestRestore(r.Client, pgCluster, pgRestore) switch pgRestore.Status.State { case v2.RestoreNew: @@ -87,9 +103,12 @@ func (r *PGRestoreReconciler) Reconcile(ctx context.Context, request reconcile.R } if _, ok := pgRestore.Annotations[pNaming.AnnotationClusterBootstrapRestore]; !ok { - if err := startRestore(ctx, r.Client, pgCluster, pgRestore); err != nil { + if err := restorer.Start(ctx); err != nil { return reconcile.Result{}, errors.Wrap(err, "start restore") } + if err := ensureFinalizers(ctx, r.Client, pgRestore); err != nil { + return reconcile.Result{}, errors.Wrap(err, "ensure finalizers") + } } pgRestore.Status.State = v2.RestoreStarting @@ -116,26 +135,23 @@ func (r *PGRestoreReconciler) Reconcile(ctx context.Context, request reconcile.R return reconcile.Result{}, nil case v2.RestoreRunning: - job := &batchv1.Job{} - err := r.Client.Get(ctx, types.NamespacedName{Name: pgCluster.Name + "-pgbackrest-restore", Namespace: pgCluster.Namespace}, job) + status, completedAt, err := restorer.ObserveStatus(ctx) if err != nil { - return reconcile.Result{}, errors.Wrap(err, "get restore job") + return reconcile.Result{}, errors.Wrap(err, "observe restore status") } - - status := checkRestoreJob(job) switch status { case v2.RestoreFailed: log.Info("Restore failed") case v2.RestoreSucceeded: log.Info("Restore succeeded") - pgRestore.Status.CompletedAt = job.Status.CompletionTime + pgRestore.Status.CompletedAt = completedAt default: log.Info("Waiting for restore to complete") return reconcile.Result{RequeueAfter: time.Second * 5}, nil } if _, ok := pgRestore.Annotations[pNaming.AnnotationClusterBootstrapRestore]; !ok { - if err := disableRestore(ctx, r.Client, pgCluster, pgRestore); err != nil { + if err := restorer.DisableRestore(ctx); err != nil { return reconcile.Result{}, errors.Wrap(err, "disable restore") } } @@ -158,7 +174,7 @@ func runFinalizers(ctx context.Context, c client.Client, pr *v2.PerconaPGRestore if k8serrors.IsNotFound(err) { pg = nil } else { - return errors.Wrap(err, "get PostgresCluster") + return errors.Wrap(err, "get PerconaPGCluster") } } @@ -167,7 +183,8 @@ func runFinalizers(ctx context.Context, c client.Client, pr *v2.PerconaPGRestore if pg == nil { return nil } - return disableRestore(ctx, c, pg, pr) + restorer := restoreutils.NewPGBackRestRestore(c, pg, pr) + return restorer.DisableRestore(ctx) }, } @@ -198,82 +215,3 @@ func ensureFinalizers(ctx context.Context, cl client.Client, pr *v2.PerconaPGRes } return nil } - -func startRestore(ctx context.Context, c client.Client, pg *v2.PerconaPGCluster, pr *v2.PerconaPGRestore) error { - orig := pg.DeepCopy() - - if pg.Annotations == nil { - pg.Annotations = make(map[string]string) - } - pg.Annotations[naming.PGBackRestRestore] = pr.Name - - postgresCluster := new(v1beta1.PostgresCluster) - if err := c.Get(ctx, client.ObjectKeyFromObject(pg), postgresCluster); err != nil { - return errors.Wrap(err, "get PostgresCluster") - } - - origPostgres := postgresCluster.DeepCopy() - - postgresCluster.Status.PGBackRest.Restore = new(v1beta1.PGBackRestJobStatus) - - if err := c.Status().Patch(ctx, postgresCluster, client.MergeFrom(origPostgres)); err != nil { - return errors.Wrap(err, "patch PGCluster") - } - - if pg.Spec.Backups.PGBackRest.Restore == nil { - pg.Spec.Backups.PGBackRest.Restore = &v1beta1.PGBackRestRestore{ - PostgresClusterDataSource: &v1beta1.PostgresClusterDataSource{}, - } - } - - tvar := true - pg.Spec.Backups.PGBackRest.Restore.Enabled = &tvar - pg.Spec.Backups.PGBackRest.Restore.RepoName = pr.Spec.RepoName - pg.Spec.Backups.PGBackRest.Restore.Options = pr.Spec.Options - - if err := c.Patch(ctx, pg, client.MergeFrom(orig)); err != nil { - return errors.Wrap(err, "patch PGCluster") - } - - if err := ensureFinalizers(ctx, c, pr); err != nil { - return errors.Wrap(err, "ensure restore finalizers") - } - - return nil -} - -func disableRestore(ctx context.Context, c client.Client, pg *v2.PerconaPGCluster, pr *v2.PerconaPGRestore) error { - if pr.Status.State == v2.RestoreSucceeded || pr.Status.State == v2.RestoreFailed { - return nil - } - - orig := pg.DeepCopy() - - if pg.Spec.Backups.PGBackRest.Restore == nil { - pg.Spec.Backups.PGBackRest.Restore = &v1beta1.PGBackRestRestore{ - PostgresClusterDataSource: &v1beta1.PostgresClusterDataSource{}, - } - } - - fvar := false - pg.Spec.Backups.PGBackRest.Restore.Enabled = &fvar - - delete(pg.Annotations, naming.LabelPGBackRestRestore) - - if err := c.Patch(ctx, pg, client.MergeFrom(orig)); err != nil { - return errors.Wrap(err, "patch PGCluster") - } - - return nil -} - -func checkRestoreJob(job *batchv1.Job) v2.PGRestoreState { - switch { - case controller.JobCompleted(job): - return v2.RestoreSucceeded - case controller.JobFailed(job): - return v2.RestoreFailed - default: - return v2.RestoreRunning - } -} diff --git a/percona/controller/pgrestore/snapshot/reconcile.go b/percona/controller/pgrestore/snapshot/reconcile.go new file mode 100644 index 0000000000..68edde7d00 --- /dev/null +++ b/percona/controller/pgrestore/snapshot/reconcile.go @@ -0,0 +1,811 @@ +package snapshot + +import ( + "context" + "fmt" + "io" + "path" + "strings" + "time" + + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" + "github.com/pkg/errors" + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/feature" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + "github.com/percona/percona-postgresql-operator/v2/percona/controller" + restoreutils "github.com/percona/percona-postgresql-operator/v2/percona/controller/pgrestore/utils" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + perconaPG "github.com/percona/percona-postgresql-operator/v2/percona/postgres" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +type snapshotRestorer struct { + cl client.Client + log logging.Logger + cluster *v2.PerconaPGCluster + backup *v2.PerconaPGBackup + restore *v2.PerconaPGRestore + podExec runtime.PodExecutor +} + +func newSnapshotRestorer( + cl client.Client, + log logging.Logger, + cluster *v2.PerconaPGCluster, + backup *v2.PerconaPGBackup, + restore *v2.PerconaPGRestore, + exec runtime.PodExecutor, +) *snapshotRestorer { + return &snapshotRestorer{ + cl: cl, + log: log, + cluster: cluster, + backup: backup, + restore: restore, + podExec: exec, + } +} + +func Reconcile( + ctx context.Context, + c client.Client, + exec runtime.PodExecutor, + pg *v2.PerconaPGCluster, + restore *v2.PerconaPGRestore, +) (reconcile.Result, error) { + log := logging.FromContext(ctx).WithName("SnapshotRestorer") + + if !feature.Enabled(ctx, feature.BackupSnapshots) { + log.Info(fmt.Sprintf("Feature gate '%s' is not enabled, skipping snapshot restore", feature.BackupSnapshots)) + return reconcile.Result{}, nil + } + + backup := &v2.PerconaPGBackup{} + if err := c.Get(ctx, types.NamespacedName{Name: restore.Spec.VolumeSnapshotBackupName, Namespace: pg.Namespace}, backup); err != nil { + return reconcile.Result{}, errors.Wrap(err, "get backup") + } + + r := newSnapshotRestorer(c, log, pg, backup, restore, exec) + + if !restore.GetDeletionTimestamp().IsZero() { + if ok, err := r.runFinalizers(ctx); err != nil { + return reconcile.Result{}, errors.Wrap(err, "run finalizers") + } else if !ok { + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + return reconcile.Result{}, nil + } + + switch restore.Status.State { + case v2.RestoreNew: + return r.reconcileNew(ctx) + case v2.RestoreStarting: + return r.reconcileStarting(ctx) + case v2.RestoreRunning: + return r.reconcileRunning(ctx) + case v2.RestoreSucceeded, v2.RestoreFailed: + ok, err := r.runFinalizers(ctx) + if err != nil { + return reconcile.Result{}, errors.Wrap(err, "run finalizers") + } + if !ok { + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + return reconcile.Result{}, nil + } + return reconcile.Result{}, nil +} + +func (r *snapshotRestorer) reconcileNew(ctx context.Context) (reconcile.Result, error) { + if restore := r.cluster.Spec.Backups.PGBackRest.Restore; restore != nil && restore.Enabled != nil && *restore.Enabled { + r.log.Info("Waiting for another restore to finish") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + restores := &v2.PerconaPGRestoreList{} + if err := r.cl.List(ctx, restores, client.InNamespace(r.cluster.Namespace)); err != nil { + return reconcile.Result{}, errors.Wrap(err, "list restores") + } + for _, restore := range restores.Items { + if restore.Spec.PGCluster != r.cluster.Name || restore.IsCompleted() || restore.GetName() == r.restore.GetName() { + continue + } + r.log.Info("Waiting for another restore to finish") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + if err := r.restore.UpdateStatus(ctx, r.cl, func(restore *v2.PerconaPGRestore) { + restore.Status.State = v2.RestoreStarting + }); err != nil { + return reconcile.Result{}, errors.Wrap(err, "update restore status") + } + r.log.Info("Snapshot restore is starting") + return reconcile.Result{}, nil +} + +func (r *snapshotRestorer) reconcileStarting(ctx context.Context) (reconcile.Result, error) { + if ok, err := r.suspendAllInstances(ctx); err != nil { + return reconcile.Result{}, errors.Wrap(err, "shutdown cluster") + } else if !ok { + r.log.Info("Waiting for instances to be suspended") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + if err := r.ensureFinalizers(ctx); err != nil { + return reconcile.Result{}, errors.Wrap(err, "ensure finalizers") + } + + if err := r.restore.UpdateStatus(ctx, r.cl, func(restore *v2.PerconaPGRestore) { + restore.Status.State = v2.RestoreRunning + }); err != nil { + return reconcile.Result{}, errors.Wrap(err, "update restore status") + } + + r.log.Info("Snapshot restore is running") + return reconcile.Result{}, nil +} + +func (r *snapshotRestorer) reconcileRunning(ctx context.Context) (reconcile.Result, error) { + instances := &appsv1.StatefulSetList{} + if err := r.cl.List(ctx, instances, &client.ListOptions{ + Namespace: r.cluster.GetNamespace(), + LabelSelector: labels.SelectorFromSet(map[string]string{ + naming.LabelCluster: r.cluster.Name, + naming.LabelData: naming.DataPostgres, + }), + }); err != nil { + return reconcile.Result{}, errors.Wrap(err, "list instances") + } + + if ok, err := r.reconcileInstances(ctx, instances); err != nil { + return reconcile.Result{}, errors.Wrap(err, "reconcile instances") + } else if !ok { + r.log.Info("Waiting for instances PVCs to be reconciled") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + // Prepare PVCs + if ok, err := r.runPrepareJob(ctx, instances); err != nil { + return reconcile.Result{}, errors.Wrap(err, "run prepare job") + } else if !ok { + r.log.Info("Preparing PVCs") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + if err := r.reconcilePrepareJobAnnotation(ctx); err != nil { + return reconcile.Result{}, errors.Wrap(err, "reconcile prepare job annotation") + } + + // Run PITR if needed + if ok, err := r.restorePITR(ctx); err != nil { + return reconcile.Result{}, errors.Wrap(err, "restore PITR") + } else if !ok { + r.log.Info("Waiting for PITR to complete") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + // Recreate DCS so that cluster can be bootstrapped with new data. + if err := r.reconcileLeaderEndpoints(ctx); err != nil { + return reconcile.Result{}, errors.Wrap(err, "reconcile leader endpoints") + } + + if ok, err := r.unsuspendAllInstances(ctx); err != nil { + return reconcile.Result{}, errors.Wrap(err, "resume cluster") + } else if !ok { + r.log.Info("Waiting for instances to be unsuspended") + return reconcile.Result{RequeueAfter: time.Second * 5}, nil + } + + if err := r.restore.UpdateStatus(ctx, r.cl, func(restore *v2.PerconaPGRestore) { + restore.Status.State = v2.RestoreSucceeded + restore.Status.CompletedAt = &metav1.Time{Time: time.Now()} + }); err != nil { + return reconcile.Result{}, errors.Wrap(err, "update restore status") + } + + r.log.Info("Snapshot restore is complete") + return reconcile.Result{}, nil +} + +func (r *snapshotRestorer) reconcileInstances(ctx context.Context, instances *appsv1.StatefulSetList) (bool, error) { + done := true + for _, instance := range instances.Items { + if ok, err := r.reconcileInstance(ctx, &instance); err != nil { + return false, errors.Wrap(err, "reconcile instance") + } else if !ok { + done = false + } + } + return done, nil +} + +func (r *snapshotRestorer) reconcileInstance(ctx context.Context, instance *appsv1.StatefulSet) (bool, error) { + dataOk, err := r.reconcileDataVolume(ctx, instance) + if err != nil { + return false, errors.Wrap(err, "reconcile data volume") + } + + walOk, err := r.reconcileWALVolume(ctx, instance) + if err != nil { + return false, errors.Wrap(err, "reconcile WAL volume") + } + + tablespaceOk, err := r.reconcileTablespaceVolumes(ctx, instance) + if err != nil { + return false, errors.Wrap(err, "reconcile tablespace volumes") + } + + return dataOk && walOk && tablespaceOk, nil +} + +func (r *snapshotRestorer) reconcileDataVolume( + ctx context.Context, + instance *appsv1.StatefulSet, +) (bool, error) { + if r.backup.Status.Snapshot == nil || r.backup.Status.Snapshot.DataVolumeSnapshotRef == nil { + return false, errors.New("data volume snapshot not known") + } + + pvc := &corev1.PersistentVolumeClaim{ObjectMeta: naming.InstancePostgresDataVolume(instance)} + snapshotName := *r.backup.Status.Snapshot.DataVolumeSnapshotRef + volCtxInfo := volumeContextInfo{role: naming.RolePostgresData} + return r.reconcileInstancePVC(ctx, volCtxInfo, pvc, instance, snapshotName) +} + +func (r *snapshotRestorer) reconcileWALVolume( + ctx context.Context, + instance *appsv1.StatefulSet, +) (bool, error) { + if r.backup.Status.Snapshot == nil || r.backup.Status.Snapshot.WALVolumeSnapshotRef == nil { + return true, nil + } + + pvc := &corev1.PersistentVolumeClaim{ObjectMeta: naming.InstancePostgresWALVolume(instance)} + snapshotName := *r.backup.Status.Snapshot.WALVolumeSnapshotRef + volCtxInfo := volumeContextInfo{role: naming.RolePostgresWAL} + return r.reconcileInstancePVC(ctx, volCtxInfo, pvc, instance, snapshotName) +} + +func (r *snapshotRestorer) reconcileTablespaceVolumes(ctx context.Context, instance *appsv1.StatefulSet) (bool, error) { + if r.backup.Status.Snapshot == nil || len(r.backup.Status.Snapshot.TablespaceVolumeSnapshotRefs) == 0 { + return true, nil + } + + done := true + for tsName, snapshotName := range r.backup.Status.Snapshot.TablespaceVolumeSnapshotRefs { + pvc := &corev1.PersistentVolumeClaim{ObjectMeta: naming.InstanceTablespaceDataVolume(instance, tsName)} + volCtxInfo := volumeContextInfo{role: naming.RoleTablespace, tablespaceName: tsName} + ok, err := r.reconcileInstancePVC(ctx, volCtxInfo, pvc, instance, snapshotName) + if err != nil { + return false, errors.Wrap(err, "reconcile tablespace volume") + } + if !ok { + done = false + } + } + return done, nil +} + +func (r *snapshotRestorer) reconcileInstancePVC( + ctx context.Context, + volCtxInfo volumeContextInfo, + pvc *corev1.PersistentVolumeClaim, + instance *appsv1.StatefulSet, + snapshotName string, +) (bool, error) { + observedPVC := &corev1.PersistentVolumeClaim{} + err := r.cl.Get(ctx, client.ObjectKeyFromObject(pvc), observedPVC) + if k8serrors.IsNotFound(err) { + if err := r.createPVCFromSnapshot(ctx, volCtxInfo, pvc, instance, snapshotName); err != nil { + return false, errors.Wrap(err, "create PVC from data source") + } + return true, nil + } else if err != nil { + return false, errors.Wrap(err, "get observed PVC") + } + + if observedPVC.GetAnnotations()[pNaming.AnnotationSnapshotRestore] == r.restore.GetName() { + return true, nil + } + + if !observedPVC.GetDeletionTimestamp().IsZero() { + return false, nil + } + + // Delete it so we can recreate + if err := r.cl.Delete(ctx, observedPVC); err != nil { + return false, errors.Wrap(err, "delete PVC") + } + return false, nil +} + +func (r *snapshotRestorer) createPVCFromSnapshot( + ctx context.Context, + volCtxInfo volumeContextInfo, + pvc *corev1.PersistentVolumeClaim, + instance *appsv1.StatefulSet, + snapshotName string, +) error { + instanceSetName := instance.GetLabels()[naming.LabelInstanceSet] + if instanceSetName == "" { + return errors.New("instance set name is not known") + } + + dataSource := &corev1.TypedLocalObjectReference{ + APIGroup: ptr.To(volumesnapshotv1.GroupName), + Kind: pNaming.KindVolumeSnapshot, + Name: snapshotName, + } + spec, err := r.pvcSpecFromDataSource(volCtxInfo, instanceSetName, dataSource) + if err != nil { + return errors.Wrap(err, "get PVC spec from data source") + } + pvc.Spec = spec + pvc.SetAnnotations(map[string]string{ + pNaming.AnnotationSnapshotRestore: r.restore.GetName(), + }) + if err := r.cl.Create(ctx, pvc); err != nil { + return errors.Wrap(err, "create PVC") + } + return nil +} + +type volumeContextInfo struct { + role string + tablespaceName string +} + +func (r *snapshotRestorer) pvcSpecFromDataSource( + volCtxInfo volumeContextInfo, + instanceSetName string, + dataSource *corev1.TypedLocalObjectReference, +) (corev1.PersistentVolumeClaimSpec, error) { + var instanceSetSpec *v2.PGInstanceSetSpec + for _, instanceSet := range r.cluster.Spec.InstanceSets { + if instanceSet.Name == instanceSetName { + instanceSetSpec = &instanceSet + break + } + } + if instanceSetSpec == nil { + return corev1.PersistentVolumeClaimSpec{}, errors.New("instance set not found") + } + + var volSpec *corev1.PersistentVolumeClaimSpec + switch volCtxInfo.role { + case naming.RolePostgresData: + volSpec = &instanceSetSpec.DataVolumeClaimSpec + case naming.RolePostgresWAL: + volSpec = instanceSetSpec.WALVolumeClaimSpec + case naming.RoleTablespace: + tablespaceIdx := -1 + for i, ts := range instanceSetSpec.TablespaceVolumes { + if ts.Name == volCtxInfo.tablespaceName { + tablespaceIdx = i + break + } + } + if tablespaceIdx == -1 { + return corev1.PersistentVolumeClaimSpec{}, errors.New("tablespace not found") + } + volSpec = &instanceSetSpec.TablespaceVolumes[tablespaceIdx].DataVolumeClaimSpec + } + + if volSpec == nil { + return corev1.PersistentVolumeClaimSpec{}, errors.New("volume spec not found in instance spec") + } + + dataVolSpec := *volSpec + dataVolSpec.DataSource = dataSource + return dataVolSpec, nil +} + +func (r *snapshotRestorer) reconcileLeaderEndpoints(ctx context.Context) error { + postgresCluster := &crunchyv1beta1.PostgresCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.cluster.Name, + Namespace: r.cluster.Namespace, + }, + } + + //nolint:staticcheck + leaderEp := &corev1.Endpoints{ObjectMeta: naming.PatroniLeaderEndpoints(postgresCluster)} + if err := r.cl.Get(ctx, client.ObjectKeyFromObject(leaderEp), leaderEp); err != nil { + return client.IgnoreNotFound(err) + } + + if len(leaderEp.Subsets) > 0 { + return nil + } + + if err := r.cl.Delete(ctx, leaderEp); client.IgnoreNotFound(err) != nil { + return errors.Wrap(err, "delete leader endpoints") + } + return nil +} + +func (r *snapshotRestorer) suspendAllInstances(ctx context.Context) (bool, error) { + instances := &appsv1.StatefulSetList{} + if err := r.cl.List(ctx, instances, &client.ListOptions{ + Namespace: r.cluster.GetNamespace(), + LabelSelector: labels.SelectorFromSet(map[string]string{ + naming.LabelCluster: r.cluster.Name, + naming.LabelData: naming.DataPostgres, + }), + }); err != nil { + return false, errors.Wrap(err, "list instances") + } + + allSuspended := true + for _, instance := range instances.Items { + if suspended, err := perconaPG.SuspendInstance(ctx, r.cl, client.ObjectKeyFromObject(&instance)); err != nil { + return false, errors.Wrap(err, "suspend instance") + } else if !suspended { + allSuspended = false + } + } + return allSuspended, nil +} + +func (r *snapshotRestorer) unsuspendAllInstances(ctx context.Context) (bool, error) { + instances := &appsv1.StatefulSetList{} + if err := r.cl.List(ctx, instances, &client.ListOptions{ + Namespace: r.cluster.GetNamespace(), + LabelSelector: labels.SelectorFromSet(map[string]string{ + naming.LabelCluster: r.cluster.Name, + naming.LabelData: naming.DataPostgres, + }), + }); err != nil { + return false, errors.Wrap(err, "list instances") + } + + allUnsuspended := true + for _, instance := range instances.Items { + if unsuspended, err := perconaPG.UnsuspendInstance(ctx, r.cl, client.ObjectKeyFromObject(&instance)); err != nil { + return false, errors.Wrap(err, "unsuspend instance") + } else if !unsuspended { + allUnsuspended = false + } + } + return allUnsuspended, nil +} + +func (r *snapshotRestorer) ensureFinalizers(ctx context.Context) error { + orig := r.restore.DeepCopy() + + finalizers := []string{pNaming.FinalizerSnapshotRestore} + finalizersChanged := false + for _, f := range finalizers { + if controllerutil.AddFinalizer(r.restore, f) { + finalizersChanged = true + } + } + if !finalizersChanged { + return nil + } + + if err := r.cl.Patch(ctx, r.restore.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "patch finalizers") + } + return nil +} + +func (r *snapshotRestorer) runFinalizers(ctx context.Context) (bool, error) { + finalizers := map[string]controller.FinalizerFunc[*v2.PerconaPGRestore]{ + pNaming.FinalizerSnapshotRestore: r.finalizeSnapshotRestore(r.cl, r.restore), + } + + finished := true + for finalizer, f := range finalizers { + done, err := controller.RunFinalizer(ctx, r.cl, r.restore, finalizer, f) + if err != nil { + return false, errors.Wrapf(err, "run finalizer %s", finalizer) + } + if !done { + finished = false + } + } + return finished, nil +} + +func (r *snapshotRestorer) finalizeSnapshotRestore(_ client.Client, _ *v2.PerconaPGRestore) func(ctx context.Context, restore *v2.PerconaPGRestore) error { + return func(ctx context.Context, restore *v2.PerconaPGRestore) error { + if done, err := r.unsuspendAllInstances(ctx); err != nil { + return errors.Wrap(err, "resume cluster") + } else if !done { + return controller.ErrFinalizerPending + } + + if err := r.cleanupSkipRecoveryFile(ctx); err != nil { + return errors.Wrap(err, "cleanup") + } + return nil + } +} + +func (r *snapshotRestorer) restorePITR(ctx context.Context) (bool, error) { + if r.restore.Spec.RepoName == nil { + return true, nil + } + + pgbackrestRestore := restoreutils.NewPGBackRestRestore(r.cl, r.cluster, r.restore) + status, _, err := pgbackrestRestore.ObserveStatus(ctx) + if err != nil { + return false, errors.Wrap(err, "observe PITR status") + } + + switch status { + case v2.RestoreNew: + case v2.RestoreStarting: + return false, pgbackrestRestore.Start(ctx) + case v2.RestoreRunning: + return false, nil + case v2.RestoreSucceeded: + return true, pgbackrestRestore.DisableRestore(ctx) + case v2.RestoreFailed: + if err := r.restore.UpdateStatus(ctx, r.cl, func(restore *v2.PerconaPGRestore) { + restore.Status.State = v2.RestoreFailed + }); err != nil { + return false, errors.Wrap(err, "update restore status") + } + return true, nil + } + return false, nil +} + +func (r *snapshotRestorer) reconcilePrepareJobAnnotation(ctx context.Context) error { + if _, ok := r.restore.GetAnnotations()[pNaming.AnnotationPVCsPreparedAt]; ok { + return nil + } + + orig := r.restore.DeepCopy() + annotations := r.restore.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + annotations[pNaming.AnnotationPVCsPreparedAt] = time.Now().Format(time.RFC3339) + r.restore.SetAnnotations(annotations) + if err := r.cl.Patch(ctx, r.restore.DeepCopy(), client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "patch restore annotations") + } + return nil +} + +// prepares PVCs before starting the cluster. +func (r *snapshotRestorer) runPrepareJob(ctx context.Context, instances *appsv1.StatefulSetList) (bool, error) { + jobName := r.restore.GetName() + "-prepare" + job := &batchv1.Job{ + ObjectMeta: metav1.ObjectMeta{ + Name: jobName, + Namespace: r.cluster.GetNamespace(), + }, + } + + // PVC already prepared, delete and return. + if _, ok := r.restore.GetAnnotations()[pNaming.AnnotationPVCsPreparedAt]; ok { + return true, client.IgnoreNotFound(r.cl.Delete(ctx, job, + client.PropagationPolicy(metav1.DeletePropagationForeground))) + } + + err := r.cl.Get(ctx, client.ObjectKeyFromObject(job), job) + if k8serrors.IsNotFound(err) { + generatePrepareJob(job, instances, r.cluster, r.restore) + if err := controllerutil.SetControllerReference(r.restore, job, r.cl.Scheme()); err != nil { + return false, errors.Wrap(err, "set controller reference") + } + if err := r.cl.Create(ctx, job); err != nil { + return false, errors.Wrap(err, "create prepare job") + } + return false, nil + } else if err != nil { + return false, errors.Wrap(err, "get prepare job") + } + + if !job.Status.CompletionTime.IsZero() && job.Status.Succeeded > 0 { + return true, nil + } + + if job.Status.Failed > 0 { + if err := r.restore.UpdateStatus(ctx, r.cl, func(restore *v2.PerconaPGRestore) { + restore.Status.State = v2.RestoreFailed + }); err != nil { + return false, errors.Wrap(err, "update restore status") + } + return true, nil + } + return false, nil +} + +// instanceSetSpecForName returns the PGInstanceSetSpec for the given instance set name, or nil if not found. +func instanceSetSpecForName(cluster *v2.PerconaPGCluster, name string) *v2.PGInstanceSetSpec { + for i := range cluster.Spec.InstanceSets { + if cluster.Spec.InstanceSets[i].Name == name { + return &cluster.Spec.InstanceSets[i] + } + } + return nil +} + +// instancePrepareInfo holds mount paths for an instance used by the snapshot prepare job. +// dataMountPath is empty when PITR + dedicated WAL (data volume not mounted). +// walMountPath is empty when no dedicated WAL volume. +type instancePrepareInfo struct { + dataMountPath string + walMountPath string +} + +func generatePrepareJob( + job *batchv1.Job, + instances *appsv1.StatefulSetList, + cluster *v2.PerconaPGCluster, + restore *v2.PerconaPGRestore, +) { + pitrEnabled := restore.Spec.RepoName != nil && restore.Spec.VolumeSnapshotBackupName != "" + pgVersion := cluster.Spec.PostgresVersion + + volumes, volumeMounts, instanceInfos := buildPrepareJobVolumes(instances, cluster, pitrEnabled) + + script := buildPrepareJobScript(instanceInfos, pgVersion, pitrEnabled) + + containerName := "snapshot-prepare" + job.Spec = batchv1.JobSpec{ + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + naming.DefaultContainerAnnotation: containerName, + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Name: containerName, + Image: cluster.Spec.Image, + Command: []string{"bash", "-c", script}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("50m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + }, + VolumeMounts: volumeMounts, + }}, + Volumes: volumes, + RestartPolicy: corev1.RestartPolicyNever, + }, + }, + } +} + +func buildPrepareJobVolumes( + instances *appsv1.StatefulSetList, + cluster *v2.PerconaPGCluster, + pitrEnabled bool, +) ([]corev1.Volume, []corev1.VolumeMount, []instancePrepareInfo) { + var volumes []corev1.Volume + var volumeMounts []corev1.VolumeMount + var instanceInfos []instancePrepareInfo + + for _, instance := range instances.Items { + instanceSetSpec := instanceSetSpecForName(cluster, instance.Labels[naming.LabelInstanceSet]) + hasWALVolume := instanceSetSpec != nil && instanceSetSpec.WALVolumeClaimSpec != nil + + // When PITR + dedicated WAL volumes, we only clear the WAL directory; no need to mount data. + needDataVolume := !pitrEnabled || !hasWALVolume + + var info instancePrepareInfo + + if needDataVolume { + info.dataMountPath = path.Join("/", instance.GetName(), "pgdata") + volumes, volumeMounts = appendDataVolume(volumes, volumeMounts, &instance, info.dataMountPath) + } + + if hasWALVolume { + info.walMountPath = path.Join("/", instance.GetName(), "pgwal") + volumes, volumeMounts = appendWALVolume(volumes, volumeMounts, &instance, info.walMountPath) + } + + instanceInfos = append(instanceInfos, info) + } + + return volumes, volumeMounts, instanceInfos +} + +func appendDataVolume(volumes []corev1.Volume, mounts []corev1.VolumeMount, instance *appsv1.StatefulSet, mountPath string) ([]corev1.Volume, []corev1.VolumeMount) { + name := instance.GetName() + "-pgdata" + volumes = append(volumes, corev1.Volume{ + Name: name, + VolumeSource: corev1.VolumeSource{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: naming.InstancePostgresDataVolume(instance).Name, + }, + }, + }) + mounts = append(mounts, corev1.VolumeMount{Name: name, MountPath: mountPath}) + return volumes, mounts +} + +func appendWALVolume(volumes []corev1.Volume, mounts []corev1.VolumeMount, instance *appsv1.StatefulSet, mountPath string) ([]corev1.Volume, []corev1.VolumeMount) { + name := instance.GetName() + "-pgwal" + volumes = append(volumes, corev1.Volume{ + Name: name, + VolumeSource: corev1.VolumeSource{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: naming.InstancePostgresWALVolume(instance).Name, + }, + }, + }) + mounts = append(mounts, corev1.VolumeMount{Name: name, MountPath: mountPath}) + return volumes, mounts +} + +func buildPrepareJobScript(instanceInfos []instancePrepareInfo, pgVersion int, pitrEnabled bool) string { + scriptParts := []string{"set -e"} + walDirSuffix := fmt.Sprintf("pg%d_wal", pgVersion) + dataDirSuffix := fmt.Sprintf("pg%d", pgVersion) + + for _, info := range instanceInfos { + if pitrEnabled { + // Clear WAL files so PITR restore can fetch from repo. WAL lives under WAL mount + // when dedicated volume is used, otherwise under pgdata. + walBase := info.dataMountPath + if info.walMountPath != "" { + walBase = info.walMountPath + } + walDir := path.Join(walBase, walDirSuffix) + scriptParts = append(scriptParts, fmt.Sprintf("find %q -mindepth 1 -delete", walDir)) + } else { + // Signal restore_command to skip WAL recovery for consistency with snapshot data. + dataDir := path.Join(info.dataMountPath, dataDirSuffix) + signalFile := path.Join(dataDir, "skip-wal-recovery") + scriptParts = append(scriptParts, fmt.Sprintf("touch %q", signalFile)) + } + } + + return strings.Join(scriptParts, "\n") +} + +// We create a $PGDATA/skip-wal-recovery file during the snapshot restore when no PITR is specified. +// This method will cleanup this file after the restore is completed. +func (r *snapshotRestorer) cleanupSkipRecoveryFile(ctx context.Context) error { + if r.restore.Spec.RepoName != nil { + return nil + } + + pods := &corev1.PodList{} + if err := r.cl.List(ctx, pods, &client.ListOptions{ + Namespace: r.cluster.GetNamespace(), + LabelSelector: labels.SelectorFromSet(map[string]string{ + naming.LabelCluster: r.cluster.Name, + naming.LabelData: naming.DataPostgres, + }), + }); err != nil { + return errors.Wrap(err, "list pods") + } + + rmScript := `rm -f "${PGDATA}/skip-wal-recovery"` + for _, pod := range pods.Items { + if err := r.podExec(ctx, r.cluster.GetNamespace(), pod.GetName(), naming.ContainerDatabase, nil, io.Discard, nil, "sh", "-c", rmScript); err != nil { + return err + } + } + + return nil +} diff --git a/percona/controller/pgrestore/snapshot/reconcile_test.go b/percona/controller/pgrestore/snapshot/reconcile_test.go new file mode 100644 index 0000000000..fe91672388 --- /dev/null +++ b/percona/controller/pgrestore/snapshot/reconcile_test.go @@ -0,0 +1,910 @@ +package snapshot + +import ( + "context" + "io" + "path" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + volumesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" + "github.com/percona/percona-postgresql-operator/v2/internal/controller/runtime" + "github.com/percona/percona-postgresql-operator/v2/internal/logging" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +func TestGeneratePrepareJob(t *testing.T) { + ns := "test-ns" + clusterName := "my-cluster" + postgresVersion := 15 + image := "postgres:15" + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + PostgresVersion: postgresVersion, + Image: image, + }, + } + + makeInstance := func(name string) appsv1.StatefulSet { + return appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + }, + } + } + + t.Run("single instance without PITR", func(t *testing.T) { + job := &batchv1.Job{} + instances := &appsv1.StatefulSetList{ + Items: []appsv1.StatefulSet{makeInstance("my-cluster-instance-0")}, + } + restore := &v2.PerconaPGRestore{ + ObjectMeta: metav1.ObjectMeta{Name: "my-restore", Namespace: ns}, + Spec: v2.PerconaPGRestoreSpec{ + PGCluster: clusterName, + VolumeSnapshotBackupName: "my-backup", + // RepoName nil and VolumeSnapshotBackupName set = no PITR + }, + } + + generatePrepareJob(job, instances, cluster, restore) + + require.Len(t, job.Spec.Template.Spec.Containers, 1) + container := job.Spec.Template.Spec.Containers[0] + assert.Equal(t, "snapshot-prepare", container.Name) + assert.Equal(t, image, container.Image) + assert.Equal(t, []string{"bash", "-c"}, container.Command[:2]) + + assert.Equal(t, resource.MustParse("50m"), container.Resources.Requests[corev1.ResourceCPU]) + assert.Equal(t, resource.MustParse("32Mi"), container.Resources.Requests[corev1.ResourceMemory]) + + // No PITR: script should touch skip-wal-recovery files + script := container.Command[2] + dataDir := path.Join("my-cluster-instance-0", "pgdata", "pg15") + assert.Contains(t, script, "touch") + assert.Contains(t, script, path.Join(dataDir, "skip-wal-recovery")) + + // Volume and mount for instance + require.Len(t, job.Spec.Template.Spec.Volumes, 1) + assert.Equal(t, "my-cluster-instance-0-pgdata", job.Spec.Template.Spec.Volumes[0].Name) + assert.Equal(t, "my-cluster-instance-0-pgdata", job.Spec.Template.Spec.Volumes[0].PersistentVolumeClaim.ClaimName) + + require.Len(t, container.VolumeMounts, 1) + assert.Equal(t, "my-cluster-instance-0-pgdata", container.VolumeMounts[0].Name) + assert.Equal(t, path.Join("/", "my-cluster-instance-0", "pgdata"), container.VolumeMounts[0].MountPath) + + assert.Equal(t, corev1.RestartPolicyNever, job.Spec.Template.Spec.RestartPolicy) + }) + + t.Run("multiple instances without PITR", func(t *testing.T) { + job := &batchv1.Job{} + instances := &appsv1.StatefulSetList{ + Items: []appsv1.StatefulSet{ + makeInstance("my-cluster-instance-0"), + makeInstance("my-cluster-instance-1"), + }, + } + restore := &v2.PerconaPGRestore{ + ObjectMeta: metav1.ObjectMeta{Name: "my-restore", Namespace: ns}, + Spec: v2.PerconaPGRestoreSpec{ + PGCluster: clusterName, + VolumeSnapshotBackupName: "my-backup", + }, + } + + generatePrepareJob(job, instances, cluster, restore) + + container := job.Spec.Template.Spec.Containers[0] + script := container.Command[2] + + // Both instances should have skip-wal-recovery + assert.Contains(t, script, path.Join("my-cluster-instance-0", "pgdata", "pg15", "skip-wal-recovery")) + assert.Contains(t, script, path.Join("my-cluster-instance-1", "pgdata", "pg15", "skip-wal-recovery")) + + require.Len(t, job.Spec.Template.Spec.Volumes, 2) + assert.Equal(t, []string{"my-cluster-instance-0-pgdata", "my-cluster-instance-1-pgdata"}, + []string{job.Spec.Template.Spec.Volumes[0].Name, job.Spec.Template.Spec.Volumes[1].Name}) + }) + + t.Run("with PITR clears WAL directory", func(t *testing.T) { + job := &batchv1.Job{} + instances := &appsv1.StatefulSetList{ + Items: []appsv1.StatefulSet{makeInstance("my-cluster-instance-0")}, + } + restore := &v2.PerconaPGRestore{ + ObjectMeta: metav1.ObjectMeta{Name: "my-restore", Namespace: ns}, + Spec: v2.PerconaPGRestoreSpec{ + PGCluster: clusterName, + RepoName: ptr.To("repo1"), + VolumeSnapshotBackupName: "my-backup", + }, + } + + generatePrepareJob(job, instances, cluster, restore) + + container := job.Spec.Template.Spec.Containers[0] + script := container.Command[2] + + // PITR: script should find/delete WAL dir, not touch skip-wal-recovery + walDir := path.Join("my-cluster-instance-0", "pgdata", "pg15_wal") + assert.Contains(t, script, "find") + assert.Contains(t, script, "-mindepth") + assert.Contains(t, script, "-delete") + assert.Contains(t, script, walDir) + assert.NotContains(t, script, "skip-wal-recovery") + }) + + t.Run("with PITR and dedicated WAL volume clears WAL under pgwal mount", func(t *testing.T) { + instanceSetName := "00" + instanceName := clusterName + "-" + instanceSetName + "-0" + + clusterWithWAL := cluster.DeepCopy() + clusterWithWAL.Spec.InstanceSets = v2.PGInstanceSets{ + { + Name: instanceSetName, + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + WALVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("512Mi"), + }, + }, + }, + }, + } + + instance := makeInstance(instanceName) + instance.Labels = map[string]string{ + naming.LabelInstanceSet: instanceSetName, + naming.LabelInstance: instanceName, + } + + job := &batchv1.Job{} + instances := &appsv1.StatefulSetList{Items: []appsv1.StatefulSet{instance}} + restore := &v2.PerconaPGRestore{ + ObjectMeta: metav1.ObjectMeta{Name: "my-restore", Namespace: ns}, + Spec: v2.PerconaPGRestoreSpec{ + PGCluster: clusterName, + RepoName: ptr.To("repo1"), + VolumeSnapshotBackupName: "my-backup", + }, + } + + generatePrepareJob(job, instances, clusterWithWAL, restore) + + container := job.Spec.Template.Spec.Containers[0] + script := container.Command[2] + + // WAL is on dedicated volume: script should clear /instance/pgwal/pg15_wal, not pgdata + walDir := path.Join("/", instanceName, "pgwal", "pg15_wal") + assert.Contains(t, script, "find") + assert.Contains(t, script, walDir) + assert.NotContains(t, script, path.Join("/", instanceName, "pgdata", "pg15_wal")) + + // PITR + dedicated WAL: only WAL PVC is mounted, not data + require.Len(t, job.Spec.Template.Spec.Volumes, 1) + assert.Equal(t, instanceName+"-pgwal", job.Spec.Template.Spec.Volumes[0].Name) + + require.Len(t, container.VolumeMounts, 1) + assert.Equal(t, instanceName+"-pgwal", container.VolumeMounts[0].Name) + assert.Equal(t, path.Join("/", instanceName, "pgwal"), container.VolumeMounts[0].MountPath) + }) + + t.Run("script starts with set -e", func(t *testing.T) { + job := &batchv1.Job{} + instances := &appsv1.StatefulSetList{ + Items: []appsv1.StatefulSet{makeInstance("instance-0")}, + } + restore := &v2.PerconaPGRestore{ + Spec: v2.PerconaPGRestoreSpec{ + PGCluster: clusterName, + VolumeSnapshotBackupName: "backup", + }, + } + + generatePrepareJob(job, instances, cluster, restore) + + script := job.Spec.Template.Spec.Containers[0].Command[2] + assert.True(t, strings.HasPrefix(script, "set -e\n"), + "script should start with 'set -e' for error handling, got: %q", script[:50]) + }) +} + +// noopPodExecutor is a PodExecutor that does nothing, for tests that don't need exec. +var noopPodExecutor runtime.PodExecutor = func( + _ context.Context, _, _, _ string, _ io.Reader, _, _ io.Writer, _ ...string, +) error { + return nil +} + +func TestReconcileDataVolume(t *testing.T) { + ctx := context.Background() + ns := "test-ns" + clusterName := "my-cluster" + backupName := "my-backup" + restoreName := "my-restore" + snapshotName := "my-backup-pgdata" + instanceSetName := "00" + instanceName := clusterName + "-" + instanceSetName + "-0" + + s := scheme.Scheme + require.NoError(t, corev1.AddToScheme(s)) + require.NoError(t, v2.AddToScheme(s)) + require.NoError(t, volumesnapshotv1.AddToScheme(s)) + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + PostgresVersion: 15, + InstanceSets: v2.PGInstanceSets{ + { + Name: instanceSetName, + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + }, + } + + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{ + DataVolumeSnapshotRef: ptr.To(snapshotName), + }, + }, + } + + restore := &v2.PerconaPGRestore{ + ObjectMeta: metav1.ObjectMeta{Name: restoreName, Namespace: ns}, + Spec: v2.PerconaPGRestoreSpec{PGCluster: clusterName, VolumeSnapshotBackupName: backupName}, + } + + instance := &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{Name: instanceName, Namespace: ns}, + Spec: appsv1.StatefulSetSpec{ServiceName: clusterName + "-pods"}, + } + instance.Labels = map[string]string{ + naming.LabelInstanceSet: instanceSetName, + naming.LabelInstance: instanceName, + } + + t.Run("returns error when DataVolumeSnapshotRef is nil", func(t *testing.T) { + backupNoSnapshot := backup.DeepCopy() + backupNoSnapshot.Status.Snapshot = nil + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backupNoSnapshot, restore). + WithStatusSubresource(backupNoSnapshot). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backupNoSnapshot, restore, noopPodExecutor) + ok, err := r.reconcileDataVolume(ctx, instance) + require.Error(t, err) + assert.False(t, ok) + assert.Contains(t, err.Error(), "data volume snapshot not known") + }) + + t.Run("creates PVC with correct data source when not found", func(t *testing.T) { + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileDataVolume(ctx, instance) + require.NoError(t, err) + assert.True(t, ok) + + pvcName := instanceName + "-pgdata" + pvc := &corev1.PersistentVolumeClaim{} + require.NoError(t, cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc)) + + // Verify data source points to the VolumeSnapshot + require.NotNil(t, pvc.Spec.DataSource, "PVC should have DataSource") + assert.Equal(t, snapshotName, pvc.Spec.DataSource.Name) + assert.Equal(t, volumesnapshotv1.GroupName, ptr.Deref(pvc.Spec.DataSource.APIGroup, "")) + assert.Equal(t, pNaming.KindVolumeSnapshot, pvc.Spec.DataSource.Kind) + + // Verify spec from instance set + assert.Equal(t, []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, pvc.Spec.AccessModes) + assert.Equal(t, resource.MustParse("1Gi"), pvc.Spec.Resources.Requests[corev1.ResourceStorage]) + + // Verify restore annotation + assert.Equal(t, restoreName, pvc.GetAnnotations()[pNaming.AnnotationSnapshotRestore]) + }) + + t.Run("deletes PVC when restore annotation is not found", func(t *testing.T) { + pvcName := instanceName + "-pgdata" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{}, // No AnnotationSnapshotRestore + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("500Mi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileDataVolume(ctx, instance) + require.NoError(t, err) + assert.False(t, ok, "should return false to trigger requeue") + + // PVC should be deleted + pvc := &corev1.PersistentVolumeClaim{} + err = cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc) + require.True(t, k8serrors.IsNotFound(err), "PVC should be deleted, got err: %v", err) + }) + + t.Run("deletes PVC when annotation points to different restore", func(t *testing.T) { + pvcName := instanceName + "-pgdata" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{ + pNaming.AnnotationSnapshotRestore: "other-restore", + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("2Gi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileDataVolume(ctx, instance) + require.NoError(t, err) + assert.False(t, ok) + + // PVC should be deleted so it can be recreated for this restore + pvc := &corev1.PersistentVolumeClaim{} + err = cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc) + require.True(t, k8serrors.IsNotFound(err), "PVC should be deleted, got err: %v", err) + }) + + t.Run("returns true when PVC already has restore annotation", func(t *testing.T) { + pvcName := instanceName + "-pgdata" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{ + pNaming.AnnotationSnapshotRestore: restoreName, + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileDataVolume(ctx, instance) + require.NoError(t, err) + assert.True(t, ok) + }) +} + +func TestReconcileWALVolume(t *testing.T) { + ctx := context.Background() + ns := "test-ns" + clusterName := "my-cluster" + backupName := "my-backup" + restoreName := "my-restore" + walSnapshotName := "my-backup-pgwal" + instanceSetName := "00" + instanceName := clusterName + "-" + instanceSetName + "-0" + + s := scheme.Scheme + require.NoError(t, corev1.AddToScheme(s)) + require.NoError(t, v2.AddToScheme(s)) + require.NoError(t, volumesnapshotv1.AddToScheme(s)) + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + PostgresVersion: 15, + InstanceSets: v2.PGInstanceSets{ + { + Name: instanceSetName, + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + WALVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("512Mi"), + }, + }, + }, + }, + }, + }, + } + + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{ + WALVolumeSnapshotRef: ptr.To(walSnapshotName), + }, + }, + } + + restore := &v2.PerconaPGRestore{ + ObjectMeta: metav1.ObjectMeta{Name: restoreName, Namespace: ns}, + Spec: v2.PerconaPGRestoreSpec{PGCluster: clusterName, VolumeSnapshotBackupName: backupName}, + } + + instance := &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{Name: instanceName, Namespace: ns}, + Spec: appsv1.StatefulSetSpec{ServiceName: clusterName + "-pods"}, + } + instance.Labels = map[string]string{ + naming.LabelInstanceSet: instanceSetName, + naming.LabelInstance: instanceName, + } + + t.Run("returns true when WALVolumeSnapshotRef is nil", func(t *testing.T) { + backupNoWAL := backup.DeepCopy() + backupNoWAL.Status.Snapshot.WALVolumeSnapshotRef = nil + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backupNoWAL, restore). + WithStatusSubresource(backupNoWAL). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backupNoWAL, restore, noopPodExecutor) + ok, err := r.reconcileWALVolume(ctx, instance) + require.NoError(t, err) + assert.True(t, ok, "no WAL volume to restore") + }) + + t.Run("creates PVC with correct data source when not found", func(t *testing.T) { + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileWALVolume(ctx, instance) + require.NoError(t, err) + assert.True(t, ok) + + pvcName := instanceName + "-pgwal" + pvc := &corev1.PersistentVolumeClaim{} + require.NoError(t, cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc)) + + // Verify data source points to the WAL VolumeSnapshot + require.NotNil(t, pvc.Spec.DataSource, "PVC should have DataSource") + assert.Equal(t, walSnapshotName, pvc.Spec.DataSource.Name) + assert.Equal(t, volumesnapshotv1.GroupName, ptr.Deref(pvc.Spec.DataSource.APIGroup, "")) + assert.Equal(t, pNaming.KindVolumeSnapshot, pvc.Spec.DataSource.Kind) + + // Verify spec from WALVolumeClaimSpec (512Mi, not data's 1Gi) + assert.Equal(t, []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, pvc.Spec.AccessModes) + assert.Equal(t, resource.MustParse("512Mi"), pvc.Spec.Resources.Requests[corev1.ResourceStorage]) + + // Verify restore annotation + assert.Equal(t, restoreName, pvc.GetAnnotations()[pNaming.AnnotationSnapshotRestore]) + }) + + t.Run("deletes PVC when restore annotation is not found", func(t *testing.T) { + pvcName := instanceName + "-pgwal" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{}, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("256Mi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileWALVolume(ctx, instance) + require.NoError(t, err) + assert.False(t, ok) + + pvc := &corev1.PersistentVolumeClaim{} + err = cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc) + require.True(t, k8serrors.IsNotFound(err), "PVC should be deleted, got err: %v", err) + }) + + t.Run("deletes PVC when annotation points to different restore", func(t *testing.T) { + pvcName := instanceName + "-pgwal" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{ + pNaming.AnnotationSnapshotRestore: "other-restore", + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("256Mi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileWALVolume(ctx, instance) + require.NoError(t, err) + assert.False(t, ok) + + pvc := &corev1.PersistentVolumeClaim{} + err = cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc) + require.True(t, k8serrors.IsNotFound(err), "PVC should be deleted, got err: %v", err) + }) + + t.Run("returns true when PVC already has restore annotation", func(t *testing.T) { + pvcName := instanceName + "-pgwal" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{ + pNaming.AnnotationSnapshotRestore: restoreName, + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("512Mi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileWALVolume(ctx, instance) + require.NoError(t, err) + assert.True(t, ok) + }) +} + +func TestReconcileTablespaceVolumes(t *testing.T) { + ctx := context.Background() + ns := "test-ns" + clusterName := "my-cluster" + backupName := "my-backup" + restoreName := "my-restore" + ts1Name := "ts1" + ts1SnapshotName := "my-backup-ts1-tablespace" + instanceSetName := "00" + instanceName := clusterName + "-" + instanceSetName + "-0" + + s := scheme.Scheme + require.NoError(t, corev1.AddToScheme(s)) + require.NoError(t, v2.AddToScheme(s)) + require.NoError(t, volumesnapshotv1.AddToScheme(s)) + + cluster := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: ns}, + Spec: v2.PerconaPGClusterSpec{ + PostgresVersion: 15, + InstanceSets: v2.PGInstanceSets{ + { + Name: instanceSetName, + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + TablespaceVolumes: []crunchyv1beta1.TablespaceVolume{ + { + Name: ts1Name, + DataVolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("2Gi"), + }, + }, + }, + }, + }, + }, + }, + }, + } + + backup := &v2.PerconaPGBackup{ + ObjectMeta: metav1.ObjectMeta{Name: backupName, Namespace: ns}, + Spec: v2.PerconaPGBackupSpec{PGCluster: clusterName}, + Status: v2.PerconaPGBackupStatus{ + Snapshot: &v2.SnapshotStatus{ + TablespaceVolumeSnapshotRefs: map[string]string{ts1Name: ts1SnapshotName}, + }, + }, + } + + restore := &v2.PerconaPGRestore{ + ObjectMeta: metav1.ObjectMeta{Name: restoreName, Namespace: ns}, + Spec: v2.PerconaPGRestoreSpec{PGCluster: clusterName, VolumeSnapshotBackupName: backupName}, + } + + instance := &appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{Name: instanceName, Namespace: ns}, + Spec: appsv1.StatefulSetSpec{ServiceName: clusterName + "-pods"}, + } + instance.Labels = map[string]string{ + naming.LabelInstanceSet: instanceSetName, + naming.LabelInstance: instanceName, + } + + t.Run("returns true when Snapshot is nil", func(t *testing.T) { + backupNoSnapshot := backup.DeepCopy() + backupNoSnapshot.Status.Snapshot = nil + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backupNoSnapshot, restore). + WithStatusSubresource(backupNoSnapshot). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backupNoSnapshot, restore, noopPodExecutor) + ok, err := r.reconcileTablespaceVolumes(ctx, instance) + require.NoError(t, err) + assert.True(t, ok, "no tablespace volumes to restore") + }) + + t.Run("returns true when TablespaceVolumeSnapshotRefs is empty", func(t *testing.T) { + backupEmpty := backup.DeepCopy() + backupEmpty.Status.Snapshot = &v2.SnapshotStatus{TablespaceVolumeSnapshotRefs: map[string]string{}} + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backupEmpty, restore). + WithStatusSubresource(backupEmpty). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backupEmpty, restore, noopPodExecutor) + ok, err := r.reconcileTablespaceVolumes(ctx, instance) + require.NoError(t, err) + assert.True(t, ok, "no tablespace volumes to restore") + }) + + t.Run("creates PVC with correct data source when not found", func(t *testing.T) { + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileTablespaceVolumes(ctx, instance) + require.NoError(t, err) + assert.True(t, ok) + + pvcName := instanceName + "-" + ts1Name + "-tablespace" + pvc := &corev1.PersistentVolumeClaim{} + require.NoError(t, cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc)) + + // Verify data source points to the tablespace VolumeSnapshot + require.NotNil(t, pvc.Spec.DataSource, "PVC should have DataSource") + assert.Equal(t, ts1SnapshotName, pvc.Spec.DataSource.Name) + assert.Equal(t, volumesnapshotv1.GroupName, ptr.Deref(pvc.Spec.DataSource.APIGroup, "")) + assert.Equal(t, pNaming.KindVolumeSnapshot, pvc.Spec.DataSource.Kind) + + // Verify spec from TablespaceVolumes[ts1].DataVolumeClaimSpec (2Gi, not data's 1Gi) + assert.Equal(t, []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, pvc.Spec.AccessModes) + assert.Equal(t, resource.MustParse("2Gi"), pvc.Spec.Resources.Requests[corev1.ResourceStorage]) + + // Verify restore annotation + assert.Equal(t, restoreName, pvc.GetAnnotations()[pNaming.AnnotationSnapshotRestore]) + }) + + t.Run("deletes PVC when restore annotation is not found", func(t *testing.T) { + pvcName := instanceName + "-" + ts1Name + "-tablespace" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{}, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("2Gi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileTablespaceVolumes(ctx, instance) + require.NoError(t, err) + assert.False(t, ok) + + pvc := &corev1.PersistentVolumeClaim{} + err = cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc) + require.True(t, k8serrors.IsNotFound(err), "PVC should be deleted, got err: %v", err) + }) + + t.Run("deletes PVC when annotation points to different restore", func(t *testing.T) { + pvcName := instanceName + "-" + ts1Name + "-tablespace" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{ + pNaming.AnnotationSnapshotRestore: "other-restore", + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("2Gi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileTablespaceVolumes(ctx, instance) + require.NoError(t, err) + assert.False(t, ok) + + pvc := &corev1.PersistentVolumeClaim{} + err = cl.Get(ctx, client.ObjectKey{Namespace: ns, Name: pvcName}, pvc) + require.True(t, k8serrors.IsNotFound(err), "PVC should be deleted, got err: %v", err) + }) + + t.Run("returns true when all tablespace PVCs have correct restore annotation", func(t *testing.T) { + pvcName := instanceName + "-" + ts1Name + "-tablespace" + existingPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: ns, + Annotations: map[string]string{ + pNaming.AnnotationSnapshotRestore: restoreName, + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("2Gi"), + }, + }, + }, + } + + cl := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(cluster, backup, restore, existingPVC). + WithStatusSubresource(backup). + Build() + + r := newSnapshotRestorer(cl, logging.Discard(), cluster, backup, restore, noopPodExecutor) + ok, err := r.reconcileTablespaceVolumes(ctx, instance) + require.NoError(t, err) + assert.True(t, ok) + }) +} diff --git a/percona/controller/pgrestore/utils/pgbackrest.go b/percona/controller/pgrestore/utils/pgbackrest.go new file mode 100644 index 0000000000..9e32efe488 --- /dev/null +++ b/percona/controller/pgrestore/utils/pgbackrest.go @@ -0,0 +1,119 @@ +package utils + +import ( + "context" + + "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" + "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" +) + +type PGBackRestRestore struct { + client.Client + + pgCluster *v2.PerconaPGCluster + pgRestore *v2.PerconaPGRestore +} + +func NewPGBackRestRestore(c client.Client, pgCluster *v2.PerconaPGCluster, pgRestore *v2.PerconaPGRestore) *PGBackRestRestore { + return &PGBackRestRestore{ + Client: c, + pgCluster: pgCluster, + pgRestore: pgRestore, + } +} + +func (r *PGBackRestRestore) Start(ctx context.Context) error { + orig := r.pgCluster.DeepCopy() + + if val, ok := r.pgCluster.GetAnnotations()[naming.PGBackRestRestore]; ok && val == r.pgRestore.Name { + return nil // already started + } + + if r.pgCluster.Annotations == nil { + r.pgCluster.Annotations = make(map[string]string) + } + r.pgCluster.Annotations[naming.PGBackRestRestore] = r.pgRestore.Name + + postgresCluster := new(v1beta1.PostgresCluster) + if err := r.Get(ctx, client.ObjectKeyFromObject(r.pgCluster), postgresCluster); err != nil { + return errors.Wrap(err, "get PostgresCluster") + } + + origPostgres := postgresCluster.DeepCopy() + + if postgresCluster.Status.PGBackRest == nil { + postgresCluster.Status.PGBackRest = &v1beta1.PGBackRestStatus{} + } + + postgresCluster.Status.PGBackRest.Restore = &v1beta1.PGBackRestJobStatus{} + + if err := r.Status().Patch(ctx, postgresCluster, client.MergeFrom(origPostgres)); err != nil { + return errors.Wrap(err, "patch PostgresCluster status failed trying to initialize PGBackRest restore status") + } + + if r.pgCluster.Spec.Backups.PGBackRest.Restore == nil { + r.pgCluster.Spec.Backups.PGBackRest.Restore = &v1beta1.PGBackRestRestore{ + PostgresClusterDataSource: &v1beta1.PostgresClusterDataSource{}, + } + } + + r.pgCluster.Spec.Backups.PGBackRest.Restore.Enabled = ptr.To(true) + r.pgCluster.Spec.Backups.PGBackRest.Restore.RepoName = ptr.Deref(r.pgRestore.Spec.RepoName, "") + r.pgCluster.Spec.Backups.PGBackRest.Restore.Options = r.pgRestore.Spec.Options + + if err := r.Patch(ctx, r.pgCluster, client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "patch PostgresCluster status failed trying to start restore") + } + + return nil +} + +func (r *PGBackRestRestore) DisableRestore(ctx context.Context) error { + if r.pgRestore.Status.State == v2.RestoreSucceeded || r.pgRestore.Status.State == v2.RestoreFailed { + return nil + } + + orig := r.pgCluster.DeepCopy() + + if r.pgCluster.Spec.Backups.PGBackRest.Restore == nil { + r.pgCluster.Spec.Backups.PGBackRest.Restore = &v1beta1.PGBackRestRestore{ + PostgresClusterDataSource: &v1beta1.PostgresClusterDataSource{}, + } + } + + r.pgCluster.Spec.Backups.PGBackRest.Restore.Enabled = ptr.To(false) + delete(r.pgCluster.Annotations, naming.PGBackRestRestore) + + if err := r.Patch(ctx, r.pgCluster, client.MergeFrom(orig)); err != nil { + return errors.Wrap(err, "patch PGCluster") + } + + return nil +} + +func (r *PGBackRestRestore) ObserveStatus(ctx context.Context) (v2.PGRestoreState, *metav1.Time, error) { + cluster := &v2.PerconaPGCluster{} + if err := r.Get(ctx, client.ObjectKeyFromObject(r.pgCluster), cluster); err != nil { + return v2.RestoreStarting, nil, errors.Wrap(err, "get PerconaPGCluster") + } + + if cluster.Status.PGBackRest == nil || cluster.Status.PGBackRest.Restore == nil { + return v2.RestoreStarting, nil, nil + } + restoreStatus := cluster.Status.PGBackRest.Restore + + switch { + case restoreStatus.Finished && restoreStatus.Succeeded > 0: + return v2.RestoreSucceeded, restoreStatus.CompletionTime, nil + case restoreStatus.Finished && restoreStatus.Failed > 0: + return v2.RestoreFailed, nil, nil + default: + return v2.RestoreRunning, nil, nil + } +} diff --git a/percona/naming/annotations.go b/percona/naming/annotations.go index cf36f7b6bc..c6737e96a2 100644 --- a/percona/naming/annotations.go +++ b/percona/naming/annotations.go @@ -51,4 +51,16 @@ const ( // indicate the name of the main site. // This annotation is set on standby clusters based on pgbackrest only. This is needed to calculate the replication lag. AnnotationReplicationMainSite = PrefixPerconaPGV2 + "replication-main-site" + + // AnnotationInstanceSuspended must be set on the instance StatefulSet to mark + // the instance as suspended. + AnnotationInstanceSuspended = PrefixPerconaPGV2 + "instance-suspended" + + // AnnotationSnapshotRestore is the annotation added to the data PVCs of a cluster + // to indicate the name of the PerconaPGRestore that is restoring the PVC from a snapshot. + AnnotationSnapshotRestore = PrefixPerconaPGV2 + "snapshot-restore" + + // AnnotationPVCsPreparedAt is the annotation added to the PerconaPGRestore which + // prepares the PVCs for a snapshot restore. + AnnotationPVCsPreparedAt = PrefixPerconaPGV2 + "pvcs-prepared-at" ) diff --git a/percona/naming/finalizers.go b/percona/naming/finalizers.go index d2fa2858bf..95f8131ab4 100644 --- a/percona/naming/finalizers.go +++ b/percona/naming/finalizers.go @@ -18,9 +18,15 @@ const ( // PerconaPGBackup finalizers const ( FinalizerDeleteBackup = PrefixPerconaInternal + "delete-backup" //nolint:gosec + + // FinalizerSnapshotInProgress is set on PerconaPGBackup objects. + // It ensures that any changes made to the PGCluster are reverted upon + // snapshot completion (success or failure) or premature deletion of the PGBackup. + FinalizerSnapshotInProgress = PrefixPercona + "snapshot-in-progress" //nolint:gosec ) // PerconaPGBackup job finalizers const ( - FinalizerKeepJob = PrefixPerconaInternal + "keep-job" //nolint:gosec + FinalizerKeepJob = PrefixPerconaInternal + "keep-job" //nolint:gosec + FinalizerSnapshotRestore = PrefixPerconaInternal + "snapshot-restore" //nolint:gosec ) diff --git a/percona/naming/kinds.go b/percona/naming/kinds.go new file mode 100644 index 0000000000..07bf8db248 --- /dev/null +++ b/percona/naming/kinds.go @@ -0,0 +1,6 @@ +package naming + +const ( + KindVolumeSnapshot = "VolumeSnapshot" + KindPersistentVolumeClaim = "PersistentVolumeClaim" +) diff --git a/percona/postgres/common.go b/percona/postgres/common.go index 41026ade48..da6cba7371 100644 --- a/percona/postgres/common.go +++ b/percona/postgres/common.go @@ -5,10 +5,14 @@ import ( gover "github.com/hashicorp/go-version" "github.com/pkg/errors" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/util/retry" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/percona/percona-postgresql-operator/v2/internal/naming" + pNaming "github.com/percona/percona-postgresql-operator/v2/percona/naming" v2 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/pgv2.percona.com/v2" ) @@ -54,9 +58,88 @@ func GetPrimaryPod(ctx context.Context, cli client.Client, cr *v2.PerconaPGClust return &podList.Items[0], nil } +// GetReplicaPods lists the replica pods for a given cluster. +func GetReplicaPods(ctx context.Context, cli client.Client, cr *v2.PerconaPGCluster) ([]corev1.Pod, error) { + podList := &corev1.PodList{} + + err := cli.List(ctx, podList, &client.ListOptions{ + Namespace: cr.Namespace, + LabelSelector: labels.SelectorFromSet(map[string]string{ + "app.kubernetes.io/instance": cr.GetName(), + "postgres-operator.crunchydata.com/role": naming.RolePatroniReplica, + }), + }) + if err != nil { + return nil, errors.Wrap(err, "failed to list pods") + } + + return podList.Items, nil +} + func determineVersion(cr *v2.PerconaPGCluster) string { if cr.CompareVersion("2.7.0") <= 0 { return cr.Status.PatroniVersion } return patroniVersion4 } + +// SuspendInstance suspends an instance by setting the AnnotationInstanceSuspended annotation on the StatefulSet. +// Returns true if the instance was suspended. +// Caller is responsible for waiting for the instance to be suspended. +func SuspendInstance(ctx context.Context, cli client.Client, instanceKey client.ObjectKey) (bool, error) { + sts := &appsv1.StatefulSet{} + if err := cli.Get(ctx, instanceKey, sts); err != nil { + return false, errors.Wrap(err, "failed to get stateful set") + } + + if _, ok := sts.GetAnnotations()[pNaming.AnnotationInstanceSuspended]; ok { + return sts.Status.Replicas == 0 && sts.Status.ReadyReplicas == 0, nil + } + + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + if err := cli.Get(ctx, instanceKey, sts); err != nil { + return errors.Wrap(err, "failed to get stateful set") + } + + orig := sts.DeepCopy() + annots := sts.GetAnnotations() + if annots == nil { + annots = make(map[string]string) + } + annots[pNaming.AnnotationInstanceSuspended] = "" + sts.SetAnnotations(annots) + return cli.Patch(ctx, sts, client.MergeFrom(orig)) + }); err != nil { + return false, errors.Wrap(err, "failed to update stateful set annotations") + } + return false, nil +} + +// UnsuspendInstance unsuspends an instance by removing the AnnotationInstanceSuspended annotation on the StatefulSet. +// Returns true if the instance was unsuspended. +// Caller is responsible for waiting for the instance to be unsuspended. +func UnsuspendInstance(ctx context.Context, cli client.Client, instanceKey client.ObjectKey) (bool, error) { + sts := &appsv1.StatefulSet{} + if err := cli.Get(ctx, instanceKey, sts); err != nil { + return false, errors.Wrap(err, "failed to get stateful set") + } + + if _, ok := sts.GetAnnotations()[pNaming.AnnotationInstanceSuspended]; !ok { + return sts.Status.Replicas > 0 && sts.Status.ReadyReplicas > 0, nil + } + + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + if err := cli.Get(ctx, instanceKey, sts); err != nil { + return errors.Wrap(err, "failed to get stateful set") + } + + orig := sts.DeepCopy() + annots := sts.GetAnnotations() + delete(annots, pNaming.AnnotationInstanceSuspended) + sts.SetAnnotations(annots) + return cli.Patch(ctx, sts, client.MergeFrom(orig)) + }); err != nil { + return false, errors.Wrap(err, "failed to update stateful set annotations") + } + return false, nil +} diff --git a/percona/watcher/wal.go b/percona/watcher/wal.go index 6fa0b93434..cee366961d 100644 --- a/percona/watcher/wal.go +++ b/percona/watcher/wal.go @@ -9,6 +9,7 @@ import ( "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" @@ -136,7 +137,9 @@ func getLatestBackup(ctx context.Context, cli client.Client, cr *pgv2.PerconaPGC latest := &pgv2.PerconaPGBackup{} runningBackupExists := false for _, backup := range backupList.Items { - backup := backup + if ptr.Deref(backup.Spec.Method, pgv2.BackupMethodPGBackrest) == pgv2.BackupMethodVolumeSnapshot { + continue + } switch backup.Status.State { case pgv2.BackupSucceeded: @@ -213,7 +216,7 @@ func getBackupStartTimestamp(ctx context.Context, cli client.Client, cr *pgv2.Pe return time.Time{}, errors.Wrap(PrimaryPodNotFound, err.Error()) } - pgbackrestInfo, err := pgbackrest.GetInfo(ctx, primary, backup.Spec.RepoName) + pgbackrestInfo, err := pgbackrest.GetInfo(ctx, primary, ptr.Deref(backup.Spec.RepoName, "")) if err != nil { return time.Time{}, errors.Wrap(err, "get pgbackrest info") } diff --git a/percona/watcher/wal_test.go b/percona/watcher/wal_test.go index f6442391b0..ca95309529 100644 --- a/percona/watcher/wal_test.go +++ b/percona/watcher/wal_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/percona/percona-postgresql-operator/v2/percona/testutils" @@ -331,7 +332,7 @@ func TestGetLatestCommitTimestamp(t *testing.T) { }, Spec: pgv2.PerconaPGBackupSpec{ PGCluster: "test-cluster", - RepoName: "repo1", + RepoName: ptr.To("repo1"), }, }, cluster: &pgv2.PerconaPGCluster{ diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go index 15c4433251..ae4836e765 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types.go @@ -1,12 +1,16 @@ package v2 import ( + "context" "encoding/json" "fmt" "time" v "github.com/hashicorp/go-version" + "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/retry" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" crunchyv1beta1 "github.com/percona/percona-postgresql-operator/v2/pkg/apis/postgres-operator.crunchydata.com/v1beta1" @@ -35,6 +39,7 @@ type PerconaPGBackup struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` + // +kubebuilder:validation:XValidation:rule="self.method == \"volumeSnapshot\" || has(self.repoName)",message="repoName is required when method is 'pgbackrest'" Spec PerconaPGBackupSpec `json:"spec"` Status PerconaPGBackupStatus `json:"status,omitempty"` } @@ -47,13 +52,27 @@ type PerconaPGBackupList struct { Items []PerconaPGBackup `json:"items"` } +type BackupMethod string + +const ( + BackupMethodPGBackrest BackupMethod = "pgbackrest" + BackupMethodVolumeSnapshot BackupMethod = "volumeSnapshot" +) + type PerconaPGBackupSpec struct { PGCluster string `json:"pgCluster"` + // +optional // The name of the pgBackRest repo to run the backup command against. - // +kubebuilder:validation:Required + // This is required when method is 'pgbackrest'. // +kubebuilder:validation:Pattern=^repo[1-4] - RepoName string `json:"repoName"` + RepoName *string `json:"repoName,omitempty"` + + // Method with which to perform the backup + // +kubebuilder:validation:Enum={pgbackrest,volumeSnapshot} + // +kubebuilder:default=pgbackrest + // +optional + Method *BackupMethod `json:"method,omitempty"` // Command line options to include when running the pgBackRest backup command. // https://pgbackrest.org/command.html#command-backup @@ -68,6 +87,7 @@ var PGClusterIndexerFunc client.IndexerFunc = func(obj client.Object) []string { if !ok { return nil } + return []string{backup.Spec.PGCluster} } @@ -94,6 +114,17 @@ type PerconaPGBackupStatus struct { BackupName string `json:"backupName,omitempty"` CRVersion string `json:"crVersion,omitempty"` LatestRestorableTime PITRestoreDateTime `json:"latestRestorableTime,omitempty"` + Snapshot *SnapshotStatus `json:"snapshot,omitempty"` +} + +type SnapshotStatus struct { + // Name of the VolumeSnapshot containing data volume contents. + DataVolumeSnapshotRef *string `json:"dataVolumeSnapshotRef,omitempty"` + // Name of the VolumeSnapshot containing WAL volume contents. + WALVolumeSnapshotRef *string `json:"walVolumeSnapshotRef,omitempty"` + // Names of the VolumeSnapshots containing tablespace volume contents. + // Key is the name of the tablespace, value is the name of the VolumeSnapshot. + TablespaceVolumeSnapshotRefs map[string]string `json:"tablespaceVolumeSnapshotRefs,omitempty"` } // +kubebuilder:validation:Type=string @@ -168,7 +199,13 @@ const ( ) func (b *PerconaPGBackup) Default() { - b.Spec.Options = append(b.Spec.Options, fmt.Sprintf(`--annotation="%s"="%s"`, PGBackrestAnnotationBackupName, b.Name)) + if b.Spec.Method == nil { + b.Spec.Method = ptr.To(BackupMethodPGBackrest) + } + + if *b.Spec.Method == BackupMethodPGBackrest { + b.Spec.Options = append(b.Spec.Options, fmt.Sprintf(`--annotation="%s"="%s"`, PGBackrestAnnotationBackupName, b.Name)) + } } func (b *PerconaPGBackup) CompareVersion(ver string) int { @@ -178,3 +215,16 @@ func (b *PerconaPGBackup) CompareVersion(ver string) int { backupVersion := v.Must(v.NewVersion(b.Status.CRVersion)) return backupVersion.Compare(v.Must(v.NewVersion(ver))) } + +func (pgBackup *PerconaPGBackup) UpdateStatus(ctx context.Context, cl client.Client, updateFunc func(bcp *PerconaPGBackup)) error { + return retry.RetryOnConflict(retry.DefaultBackoff, func() error { + bcp := new(PerconaPGBackup) + if err := cl.Get(ctx, client.ObjectKeyFromObject(pgBackup), bcp); err != nil { + return errors.Wrap(err, "get PGBackup") + } + + updateFunc(bcp) + + return cl.Status().Update(ctx, bcp) + }) +} diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go index e8b27d955c..d45d70d4d6 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgbackup_types_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TestPITRestoreDateTime_MarshalJSON(t *testing.T) { @@ -29,25 +30,25 @@ func TestPITRestoreDateTime_MarshalJSON(t *testing.T) { }, "non-pointer zero date time": { data: PITRestoreDateTime{ - Time: ptr(metav1.NewTime(time.Time{})), + Time: ptr.To(metav1.NewTime(time.Time{})), }, expected: `"0001-01-01 00:00:00.000000+0000"`, }, "pointer zero date time": { data: &PITRestoreDateTime{ - Time: ptr(metav1.NewTime(time.Time{})), + Time: ptr.To(metav1.NewTime(time.Time{})), }, expected: `"0001-01-01 00:00:00.000000+0000"`, }, "non-pointer with date time": { data: PITRestoreDateTime{ - Time: ptr(metav1.NewTime(time.Date(2025, time.November, 21, 13, 14, 15, 345600000, time.UTC))), + Time: ptr.To(metav1.NewTime(time.Date(2025, time.November, 21, 13, 14, 15, 345600000, time.UTC))), }, expected: `"2025-11-21 13:14:15.345600+0000"`, }, "pointer with date time": { data: &PITRestoreDateTime{ - Time: ptr(metav1.NewTime(time.Date(2025, time.November, 21, 13, 14, 15, 345600000, time.UTC))), + Time: ptr.To(metav1.NewTime(time.Date(2025, time.November, 21, 13, 14, 15, 345600000, time.UTC))), }, expected: `"2025-11-21 13:14:15.345600+0000"`, }, @@ -63,7 +64,3 @@ func TestPITRestoreDateTime_MarshalJSON(t *testing.T) { }) } } - -func ptr[T any](v T) *T { - return &v -} diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 8bb805a58d..4384177529 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -9,6 +9,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -266,6 +267,12 @@ func (cr *PerconaPGCluster) Default() { if cr.CompareVersion("2.6.0") >= 0 && cr.Spec.AutoCreateUserSchema == nil { cr.Spec.AutoCreateUserSchema = &t } + + if cr.Spec.Backups.IsVolumeSnapshotsEnabled() && + cr.Spec.Backups.VolumeSnapshots.Mode == VolumeSnapshotModeOffline && + cr.Spec.Backups.VolumeSnapshots.OfflineConfig == nil { + cr.Spec.Backups.VolumeSnapshots.OfflineConfig = DefaultOfflineSnapshotConfig() + } } func (cr *PerconaPGCluster) PostgresImage() string { @@ -526,6 +533,75 @@ type Backups struct { // Enable tracking latest restorable time TrackLatestRestorableTime *bool `json:"trackLatestRestorableTime,omitempty"` + + // VolumeSnapshots configuration + // +optional + VolumeSnapshots *VolumeSnapshots `json:"volumeSnapshots,omitempty"` +} + +type VolumeSnapshotMode string + +const ( + // VolumeSnapshotModeOffline is the mode for taking offline VolumeSnapshots. + // With this mode, the operator will stop a replica and take a snapshot of the PVC. + VolumeSnapshotModeOffline VolumeSnapshotMode = "offline" +) + +type VolumeSnapshots struct { + // Mode of the VolumeSnapshot. + // +kubebuilder:validation:Enum={offline} + // +kubebuilder:default=offline + // +optional + Mode VolumeSnapshotMode `json:"mode,omitempty"` + + // Name of the VolumeSnapshotClass to use. + // +kubebuilder:validation:Required + ClassName string `json:"className"` + + // Defines the Cron schedule for a VolumeSnapshot. + // Follows the standard Cron schedule syntax: + // https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax + // +optional + // +kubebuilder:validation:MinLength=6 + Schedule *string `json:"schedule,omitempty"` + + // Configuration for offline snapshot operations. + // Ignored if mode is not offline. + // +optional + OfflineConfig *OfflineSnapshotConfig `json:"offlineConfig,omitempty"` +} + +func DefaultOfflineSnapshotConfig() *OfflineSnapshotConfig { + return &OfflineSnapshotConfig{ + Checkpoint: &CheckpointConfig{ + Enabled: ptr.To(true), + TimeoutSeconds: ptr.To(int32(300)), + }, + } +} + +type OfflineSnapshotConfig struct { + // Checkpoint configuration for offline snapshot operations. + // +optional + Checkpoint *CheckpointConfig `json:"checkpoint,omitempty"` +} + +type CheckpointConfig struct { + // If set, a checkpoint is requested. + // +optional + // +kubebuilder:default=true + Enabled *bool `json:"enabled,omitempty"` + + // Timeout for the checkpoint operation. + // Ignored if checkpoint is not enabled. + // +optional + // +kubebuilder:validation:Minimum=30 + // +kubebuilder:default=300 + TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"` +} + +func (b Backups) IsVolumeSnapshotsEnabled() bool { + return b.VolumeSnapshots != nil && b.VolumeSnapshots.ClassName != "" } func (b Backups) IsEnabled() bool { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgrestore_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgrestore_types.go index a1e395bf1a..e242b1ee07 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgrestore_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgrestore_types.go @@ -1,7 +1,12 @@ package v2 import ( + "context" + + "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/retry" + "sigs.k8s.io/controller-runtime/pkg/client" ) func init() { @@ -24,6 +29,7 @@ type PerconaPGRestore struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` + // +kubebuilder:validation:XValidation:rule="((has(self.repoName) && self.repoName != \"\") || (has(self.volumeSnapshotBackupName) && self.volumeSnapshotBackupName != \"\"))",message="either repoName or volumeSnapshotBackupName must be set" Spec PerconaPGRestoreSpec `json:"spec"` Status PerconaPGRestoreStatus `json:"status,omitempty"` } @@ -39,14 +45,20 @@ type PerconaPGRestoreList struct { type PerconaPGRestoreSpec struct { // The name of the PerconaPGCluster to perform restore. // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="pgCluster is an immutable field" PGCluster string `json:"pgCluster"` // The name of the pgBackRest repo within the source PostgresCluster that contains the backups // that should be utilized to perform a pgBackRest restore when initializing the data source // for the new PostgresCluster. - // +kubebuilder:validation:Required // +kubebuilder:validation:Pattern=^repo[1-4] - RepoName string `json:"repoName"` + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="repoName is an immutable field" + RepoName *string `json:"repoName,omitempty"` + + // The name of the backup to perform in-place volume snapshot restores from. + // +optional + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="volumeSnapshotBackupName is an immutable field" + VolumeSnapshotBackupName string `json:"volumeSnapshotBackupName,omitempty"` // Command line options to include when running the pgBackRest restore command. // https://pgbackrest.org/command.html#command-restore @@ -69,3 +81,20 @@ type PerconaPGRestoreStatus struct { State PGRestoreState `json:"state,omitempty"` CompletedAt *metav1.Time `json:"completed,omitempty"` } + +func (r *PerconaPGRestore) IsCompleted() bool { + return r.Status.State == RestoreSucceeded || r.Status.State == RestoreFailed +} + +func (pgRestore *PerconaPGRestore) UpdateStatus(ctx context.Context, cl client.Client, updateFunc func(restore *PerconaPGRestore)) error { + return retry.RetryOnConflict(retry.DefaultBackoff, func() error { + restore := new(PerconaPGRestore) + if err := cl.Get(ctx, client.ObjectKeyFromObject(pgRestore), restore); err != nil { + return errors.Wrap(err, "get PGRestore") + } + + updateFunc(restore) + + return cl.Status().Update(ctx, restore) + }) +} diff --git a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go index 815d6481af..0962924286 100644 --- a/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go +++ b/pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go @@ -30,6 +30,11 @@ func (in *Backups) DeepCopyInto(out *Backups) { *out = new(bool) **out = **in } + if in.VolumeSnapshots != nil { + in, out := &in.VolumeSnapshots, &out.VolumeSnapshots + *out = new(VolumeSnapshots) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backups. @@ -82,6 +87,31 @@ func (in *BuiltInExtensionsSpec) DeepCopy() *BuiltInExtensionsSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CheckpointConfig) DeepCopyInto(out *CheckpointConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.TimeoutSeconds != nil { + in, out := &in.TimeoutSeconds, &out.TimeoutSeconds + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CheckpointConfig. +func (in *CheckpointConfig) DeepCopy() *CheckpointConfig { + if in == nil { + return nil + } + out := new(CheckpointConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomExtensionSpec) DeepCopyInto(out *CustomExtensionSpec) { *out = *in @@ -139,6 +169,26 @@ func (in *ExtensionsSpec) DeepCopy() *ExtensionsSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OfflineSnapshotConfig) DeepCopyInto(out *OfflineSnapshotConfig) { + *out = *in + if in.Checkpoint != nil { + in, out := &in.Checkpoint, &out.Checkpoint + *out = new(CheckpointConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OfflineSnapshotConfig. +func (in *OfflineSnapshotConfig) DeepCopy() *OfflineSnapshotConfig { + if in == nil { + return nil + } + out := new(OfflineSnapshotConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PGBackRestArchive) DeepCopyInto(out *PGBackRestArchive) { *out = *in @@ -632,6 +682,16 @@ func (in *PerconaPGBackupList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PerconaPGBackupSpec) DeepCopyInto(out *PerconaPGBackupSpec) { *out = *in + if in.RepoName != nil { + in, out := &in.RepoName, &out.RepoName + *out = new(string) + **out = **in + } + if in.Method != nil { + in, out := &in.Method, &out.Method + *out = new(BackupMethod) + **out = **in + } if in.Options != nil { in, out := &in.Options, &out.Options *out = make([]string, len(*in)) @@ -662,6 +722,11 @@ func (in *PerconaPGBackupStatus) DeepCopyInto(out *PerconaPGBackupStatus) { (*in).DeepCopyInto(*out) } in.LatestRestorableTime.DeepCopyInto(&out.LatestRestorableTime) + if in.Snapshot != nil { + in, out := &in.Snapshot, &out.Snapshot + *out = new(SnapshotStatus) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PerconaPGBackupStatus. @@ -947,6 +1012,11 @@ func (in *PerconaPGRestoreList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PerconaPGRestoreSpec) DeepCopyInto(out *PerconaPGRestoreSpec) { *out = *in + if in.RepoName != nil { + in, out := &in.RepoName, &out.RepoName + *out = new(string) + **out = **in + } if in.Options != nil { in, out := &in.Options, &out.Options *out = make([]string, len(*in)) @@ -1216,6 +1286,38 @@ func (in *ServiceExpose) DeepCopy() *ServiceExpose { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SnapshotStatus) DeepCopyInto(out *SnapshotStatus) { + *out = *in + if in.DataVolumeSnapshotRef != nil { + in, out := &in.DataVolumeSnapshotRef, &out.DataVolumeSnapshotRef + *out = new(string) + **out = **in + } + if in.WALVolumeSnapshotRef != nil { + in, out := &in.WALVolumeSnapshotRef, &out.WALVolumeSnapshotRef + *out = new(string) + **out = **in + } + if in.TablespaceVolumeSnapshotRefs != nil { + in, out := &in.TablespaceVolumeSnapshotRefs, &out.TablespaceVolumeSnapshotRefs + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotStatus. +func (in *SnapshotStatus) DeepCopy() *SnapshotStatus { + if in == nil { + return nil + } + out := new(SnapshotStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StandbySpec) DeepCopyInto(out *StandbySpec) { *out = *in @@ -1259,3 +1361,28 @@ func (in *StandbyStatus) DeepCopy() *StandbyStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSnapshots) DeepCopyInto(out *VolumeSnapshots) { + *out = *in + if in.Schedule != nil { + in, out := &in.Schedule, &out.Schedule + *out = new(string) + **out = **in + } + if in.OfflineConfig != nil { + in, out := &in.OfflineConfig, &out.OfflineConfig + *out = new(OfflineSnapshotConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSnapshots. +func (in *VolumeSnapshots) DeepCopy() *VolumeSnapshots { + if in == nil { + return nil + } + out := new(VolumeSnapshots) + in.DeepCopyInto(out) + return out +} From 32278ca7814aa14cabbf37e956f5681fddaaa4d5 Mon Sep 17 00:00:00 2001 From: Mayank Shah Date: Mon, 16 Feb 2026 17:50:00 +0530 Subject: [PATCH 297/300] CLOUD-727: Bump Go to 1.26.0 (#1442) * bump golang to 1.26.0 Signed-off-by: Mayank Shah --- .github/linters/go.mod | 2 +- .github/workflows/reviewdog.yml | 6 +++--- .github/workflows/test.yml | 2 +- Jenkinsfile | 2 +- build/postgres-operator/Dockerfile | 2 +- go.mod | 2 +- internal/testing/events/recorder.go | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/linters/go.mod b/.github/linters/go.mod index b652c5cf47..a602f0caef 100644 --- a/.github/linters/go.mod +++ b/.github/linters/go.mod @@ -1,3 +1,3 @@ module linters -go 1.25.1 +go 1.26.0 diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index 49c01a5f81..62613872fc 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/setup-go@v6 with: - go-version: '^1.25.1' + go-version: '^1.26.0' - uses: actions/checkout@v6 - name: golangci-lint uses: golangci/golangci-lint-action@v9 @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '^1.25.1' + go-version: '^1.26.0' - run: go install -v github.com/incu6us/goimports-reviser/v3@latest - run: $(go env GOPATH)/bin/goimports-reviser -imports-order "std,general,company,project" -company-prefixes "github.com/percona" ./... - uses: reviewdog/action-suggester@v1 @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '^1.25.1' + go-version: '^1.26.0' - run: go install mvdan.cc/sh/v3/cmd/shfmt@latest - run: $(go env GOPATH)/bin/shfmt -bn -ci -s -w . - name: suggester / shfmt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 524308b9bf..72df5ccb60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v6 with: - go-version: '^1.25.1' + go-version: '^1.26.0' - uses: actions/checkout@v6 - name: Basic tests run: make check diff --git a/Jenkinsfile b/Jenkinsfile index 29525a0bba..e19aa5bb18 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -506,7 +506,7 @@ pipeline { -v $WORKSPACE/src/github.com/percona/percona-postgresql-operator:/go/src/github.com/percona/percona-postgresql-operator \ -w /go/src/github.com/percona/percona-postgresql-operator \ -e GO111MODULE=on \ - golang:1.25.1 sh -c ' + golang:1.26.0 sh -c ' go install github.com/google/go-licenses@latest; /go/bin/go-licenses csv github.com/percona/percona-postgresql-operator/v2/cmd/postgres-operator \ | cut -d , -f 3 \ diff --git a/build/postgres-operator/Dockerfile b/build/postgres-operator/Dockerfile index a159bf2710..45c38b9745 100644 --- a/build/postgres-operator/Dockerfile +++ b/build/postgres-operator/Dockerfile @@ -1,6 +1,6 @@ ARG BASE_IMAGE=ubi10 -FROM --platform=${BUILDPLATFORM} golang:1.25 AS go_builder +FROM --platform=${BUILDPLATFORM} golang:1.26 AS go_builder WORKDIR /go/src/github.com/percona/percona-postgresql-operator COPY go.mod go.sum ./ diff --git a/go.mod b/go.mod index 9324403777..1d97997a60 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/percona/percona-postgresql-operator/v2 -go 1.25.1 +go 1.26.0 require ( github.com/Percona-Lab/percona-version-service v0.0.0-20230404081016-ea25e30cdcbc diff --git a/internal/testing/events/recorder.go b/internal/testing/events/recorder.go index 23c03a4c40..426740c2b8 100644 --- a/internal/testing/events/recorder.go +++ b/internal/testing/events/recorder.go @@ -89,7 +89,7 @@ func (*Recorder) AnnotatedEventf(object runtime.Object, annotations map[string]s } func (r *Recorder) Event(object runtime.Object, eventtype, reason, message string) { if r.eventf != nil { - r.eventf(object, nil, eventtype, reason, "", message) + r.eventf(object, nil, eventtype, reason, "", "%s", message) } } func (r *Recorder) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...any) { From a0928c6466adf25e33aa9cbd68fcfdcb808fd4fa Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Mon, 16 Feb 2026 15:10:03 +0100 Subject: [PATCH 298/300] K8SPG-938 fix conditions (#1435) * K8SPG-938 fix conditions * add test * add unit test * delete comment --- percona/controller/pgcluster/status.go | 15 +- percona/controller/pgcluster/status_test.go | 456 +++++++++++++++----- 2 files changed, 344 insertions(+), 127 deletions(-) diff --git a/percona/controller/pgcluster/status.go b/percona/controller/pgcluster/status.go index 1039e96fec..1d99d968a3 100644 --- a/percona/controller/pgcluster/status.go +++ b/percona/controller/pgcluster/status.go @@ -157,13 +157,13 @@ func updateConditions(cr *v2.PerconaPGCluster, status *v1beta1.PostgresClusterSt syncPgbackrestFromPostgresToPercona(cr, status) - repoCondition := meta.FindStatusCondition(status.Conditions, postgrescluster.ConditionRepoHostReady) + repoCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionRepoHostReady) if repoCondition == nil || repoCondition.Status != metav1.ConditionTrue { setClusterNotReadyCondition(metav1.ConditionFalse, postgrescluster.ConditionRepoHostReady) return } - backupCondition := meta.FindStatusCondition(status.Conditions, postgrescluster.ConditionReplicaCreate) + backupCondition := meta.FindStatusCondition(cr.Status.Conditions, postgrescluster.ConditionReplicaCreate) if backupCondition == nil || backupCondition.Status != metav1.ConditionTrue { setClusterNotReadyCondition(metav1.ConditionFalse, postgrescluster.ConditionReplicaCreate) return @@ -175,21 +175,14 @@ func updateConditions(cr *v2.PerconaPGCluster, status *v1beta1.PostgresClusterSt func syncConditionsFromPostgresToPercona(cr *v2.PerconaPGCluster, postgresStatus *v1beta1.PostgresClusterStatus) { for _, pcCond := range postgresStatus.Conditions { - existing := meta.FindStatusCondition(cr.Status.Conditions, pcCond.Type) - if existing != nil { - continue - } - - newCond := metav1.Condition{ + _ = meta.SetStatusCondition(&cr.Status.Conditions, metav1.Condition{ Type: pcCond.Type, Status: pcCond.Status, Reason: pcCond.Reason, Message: pcCond.Message, LastTransitionTime: pcCond.LastTransitionTime, ObservedGeneration: cr.Generation, - } - - cr.Status.Conditions = append(cr.Status.Conditions, newCond) + }) } } diff --git a/percona/controller/pgcluster/status_test.go b/percona/controller/pgcluster/status_test.go index ea9ed9ed68..3b308097c1 100644 --- a/percona/controller/pgcluster/status_test.go +++ b/percona/controller/pgcluster/status_test.go @@ -5,11 +5,14 @@ package pgcluster import ( "context" + "testing" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gs "github.com/onsi/gomega/gstruct" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -338,125 +341,346 @@ var _ = Describe("PG Cluster status", Ordered, func() { }) }) }) +}) - Context("Update PG cluster status.conditions", Ordered, func() { - crName := ns + "-conditions" - crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns} - - cr, err := readDefaultCR(crName, ns) - It("should read default cr.yaml and create PerconaPGCluster", func() { - Expect(err).NotTo(HaveOccurred()) - status := cr.Status - Expect(k8sClient.Create(ctx, cr)).Should(Succeed()) - cr.Status = status - Expect(k8sClient.Status().Update(ctx, cr)).Should(Succeed()) - }) - - It("should reconcile and create Crunchy PostgreCluster", func() { - _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) - Expect(err).NotTo(HaveOccurred()) - }) - - When("conditions are not set", func() { - It("should reconcile and update conditions", func() { - _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) - Expect(err).NotTo(HaveOccurred()) - }) - It("ReadyForBackup condition should be False", func() { - Eventually(func() bool { - err := k8sClient.Get(ctx, crNamespacedName, cr) - return err == nil - }, time.Second*15, time.Millisecond*250).Should(BeTrue()) - - condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) - Expect(condition).Should(Not(BeNil())) - Expect(condition.Status).Should(Equal(metav1.ConditionFalse)) - }) - }) - - When("ConditionRepoHostReady is false", func() { - It("ReadyForBackup condition should be False", func() { - updateCrunchyPGClusterStatus(ctx, crNamespacedName, func(pgc *v1beta1.PostgresCluster) { - _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ - Type: postgrescluster.ConditionRepoHostReady, - Status: metav1.ConditionFalse, - Reason: "test", - }) - _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ - Type: postgrescluster.ConditionReplicaCreate, - Status: metav1.ConditionTrue, - Reason: "test", - }) - }) - _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) - Expect(err).NotTo(HaveOccurred()) - - Eventually(func() bool { - err := k8sClient.Get(ctx, crNamespacedName, cr) - return err == nil - }, time.Second*15, time.Millisecond*250).Should(BeTrue()) - - condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) - Expect(condition.Status).Should(Equal(metav1.ConditionFalse)) - Expect(cr.Status.ObservedGeneration).Should(Equal(int64(1))) - }) - }) - - When("ConditionReplicaCreate is false", func() { - It("ReadyForBackup condition should be False", func() { - updateCrunchyPGClusterStatus(ctx, crNamespacedName, func(pgc *v1beta1.PostgresCluster) { - _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ - Type: postgrescluster.ConditionRepoHostReady, - Status: metav1.ConditionTrue, - Reason: "test", - }) - _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ - Type: postgrescluster.ConditionReplicaCreate, - Status: metav1.ConditionFalse, - Reason: "test", - }) - }) - _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) - Expect(err).NotTo(HaveOccurred()) - - Eventually(func() bool { - err := k8sClient.Get(ctx, crNamespacedName, cr) - return err == nil - }, time.Second*15, time.Millisecond*250).Should(BeTrue()) - - condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) - Expect(condition.Status).Should(Equal(metav1.ConditionFalse)) - }) - }) - - When("both are true", func() { - It("ReadyForBackup condition should be True", func() { - updateCrunchyPGClusterStatus(ctx, crNamespacedName, func(pgc *v1beta1.PostgresCluster) { - _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ - Type: postgrescluster.ConditionRepoHostReady, - Status: metav1.ConditionTrue, - Reason: "test", - }) - _ = meta.SetStatusCondition(&pgc.Status.Conditions, metav1.Condition{ - Type: postgrescluster.ConditionReplicaCreate, - Status: metav1.ConditionTrue, - Reason: "test", - }) - }) - _, err = reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName}) - Expect(err).NotTo(HaveOccurred()) - - Eventually(func() bool { - err := k8sClient.Get(ctx, crNamespacedName, cr) - return err == nil - }, time.Second*15, time.Millisecond*250).Should(BeTrue()) +// Unit tests for updateConditions function +func TestUpdateConditions(t *testing.T) { + switchover := "switching" + switchoverTimeline := int64(3) + + tests := []struct { + name string + crConditions []metav1.Condition + statusConditions []metav1.Condition + pgBackRestStatus *v1beta1.PGBackRestStatus + patroniStatus v1beta1.PatroniStatus + + expectedReadyForBackupStatus metav1.ConditionStatus + expectedReadyForBackupReason string + expectedSyncedConditions []metav1.Condition + expectedPGBackRest *v1beta1.PGBackRestStatus + expectedPatroni *v1beta1.PatroniStatus + }{ + { + name: "no conditions set - RepoHostReady missing", + expectedReadyForBackupStatus: metav1.ConditionFalse, + expectedReadyForBackupReason: postgrescluster.ConditionRepoHostReady, + }, + { + name: "RepoHostReady is false", + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionFalse, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionFalse, + expectedReadyForBackupReason: postgrescluster.ConditionRepoHostReady, + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionFalse, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + }, + }, + { + name: "RepoHostReady is true but ReplicaCreate is missing", + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionFalse, + expectedReadyForBackupReason: postgrescluster.ConditionReplicaCreate, + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + }, + }, + { + name: "RepoHostReady is true but ReplicaCreate is false", + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionFalse, + Reason: "test", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionFalse, + expectedReadyForBackupReason: postgrescluster.ConditionReplicaCreate, + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionFalse, Reason: "test"}, + }, + }, + { + name: "both conditions are true", + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionTrue, + expectedReadyForBackupReason: "AllConditionsAreTrue", + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + }, + }, + { + name: "existing ReadyForBackup condition gets updated when RepoHostReady becomes true", + crConditions: []metav1.Condition{ + { + Type: pNaming.ConditionClusterIsReadyForBackup, + Status: metav1.ConditionFalse, + Reason: postgrescluster.ConditionRepoHostReady, + }, + }, + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionTrue, + expectedReadyForBackupReason: "AllConditionsAreTrue", + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + }, + }, + { + name: "existing true condition stays true when both conditions remain true", + crConditions: []metav1.Condition{ + { + Type: pNaming.ConditionClusterIsReadyForBackup, + Status: metav1.ConditionTrue, + Reason: "AllConditionsAreTrue", + }, + }, + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionTrue, + expectedReadyForBackupReason: "AllConditionsAreTrue", + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + }, + }, + { + name: "syncs conditions from postgres status to percona cr", + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: "SomeOtherCondition", + Status: metav1.ConditionTrue, + Reason: "other", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionTrue, + expectedReadyForBackupReason: "AllConditionsAreTrue", + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: "SomeOtherCondition", Status: metav1.ConditionTrue, Reason: "other"}, + }, + }, + { + name: "existing condition on cr gets updated by sync", + crConditions: []metav1.Condition{ + { + Type: "SomeOtherCondition", + Status: metav1.ConditionFalse, + Reason: "original-reason", + }, + }, + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: "SomeOtherCondition", + Status: metav1.ConditionTrue, + Reason: "updated-reason", + }, + }, + expectedReadyForBackupStatus: metav1.ConditionTrue, + expectedReadyForBackupReason: "AllConditionsAreTrue", + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: "SomeOtherCondition", Status: metav1.ConditionTrue, Reason: "updated-reason"}, + }, + }, + { + name: "syncs pgbackrest status from postgres to percona", + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + }, + pgBackRestStatus: &v1beta1.PGBackRestStatus{ + RepoHost: &v1beta1.RepoHostStatus{Ready: true}, + }, + expectedReadyForBackupStatus: metav1.ConditionTrue, + expectedReadyForBackupReason: "AllConditionsAreTrue", + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + }, + expectedPGBackRest: &v1beta1.PGBackRestStatus{ + RepoHost: &v1beta1.RepoHostStatus{Ready: true}, + }, + }, + { + name: "syncs patroni status from postgres to percona", + statusConditions: []metav1.Condition{ + { + Type: postgrescluster.ConditionRepoHostReady, + Status: metav1.ConditionTrue, + Reason: "test", + }, + { + Type: postgrescluster.ConditionReplicaCreate, + Status: metav1.ConditionTrue, + Reason: "test", + }, + }, + patroniStatus: v1beta1.PatroniStatus{ + SystemIdentifier: "12345", + Switchover: &switchover, + SwitchoverTimeline: &switchoverTimeline, + }, + expectedReadyForBackupStatus: metav1.ConditionTrue, + expectedReadyForBackupReason: "AllConditionsAreTrue", + expectedSyncedConditions: []metav1.Condition{ + {Type: postgrescluster.ConditionRepoHostReady, Status: metav1.ConditionTrue, Reason: "test"}, + {Type: postgrescluster.ConditionReplicaCreate, Status: metav1.ConditionTrue, Reason: "test"}, + }, + expectedPatroni: &v1beta1.PatroniStatus{ + SystemIdentifier: "12345", + Switchover: &switchover, + SwitchoverTimeline: &switchoverTimeline, + }, + }, + } - condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) - Expect(condition.Status).Should(Equal(metav1.ConditionTrue)) - }) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cr := &v2.PerconaPGCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster", + Namespace: "test-ns", + Generation: 1, + }, + Status: v2.PerconaPGClusterStatus{}, + } + if tt.crConditions != nil { + cr.Status.Conditions = tt.crConditions + } + + status := &v1beta1.PostgresClusterStatus{ + Patroni: tt.patroniStatus, + } + if tt.statusConditions != nil { + status.Conditions = tt.statusConditions + } + if tt.pgBackRestStatus != nil { + status.PGBackRest = tt.pgBackRestStatus + } + + updateConditions(cr, status) + + // Verify ClusterIsReadyForBackup condition + condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup) + require.NotNil(t, condition, "ClusterIsReadyForBackup condition should be set") + assert.Equal(t, tt.expectedReadyForBackupStatus, condition.Status, "ClusterIsReadyForBackup status mismatch") + assert.Equal(t, tt.expectedReadyForBackupReason, condition.Reason, "ClusterIsReadyForBackup reason mismatch") + + // Verify synced conditions + for _, expected := range tt.expectedSyncedConditions { + synced := meta.FindStatusCondition(cr.Status.Conditions, expected.Type) + if !assert.NotNil(t, synced, "condition %s should be synced", expected.Type) { + continue + } + assert.Equal(t, expected.Status, synced.Status, "synced condition %s status mismatch", expected.Type) + assert.Equal(t, expected.Reason, synced.Reason, "synced condition %s reason mismatch", expected.Type) + assert.Equal(t, int64(1), synced.ObservedGeneration, "synced condition %s should have ObservedGeneration=1", expected.Type) + } + + // Verify PGBackRest status sync + if tt.expectedPGBackRest != nil { + require.NotNil(t, cr.Status.PGBackRest, "PGBackRest status should be synced") + require.NotNil(t, cr.Status.PGBackRest.RepoHost, "PGBackRest RepoHost should be synced") + assert.Equal(t, tt.expectedPGBackRest.RepoHost.Ready, cr.Status.PGBackRest.RepoHost.Ready, "PGBackRest RepoHost Ready mismatch") + } + + // Verify Patroni status sync + if tt.expectedPatroni != nil { + require.NotNil(t, cr.Status.Patroni.Status, "Patroni status should be synced") + assert.Equal(t, tt.expectedPatroni.SystemIdentifier, cr.Status.Patroni.Status.SystemIdentifier, "Patroni SystemIdentifier mismatch") + assert.Equal(t, tt.expectedPatroni.Switchover, cr.Status.Patroni.Status.Switchover, "Patroni Switchover mismatch") + assert.Equal(t, tt.expectedPatroni.SwitchoverTimeline, cr.Status.Patroni.Status.SwitchoverTimeline, "Patroni SwitchoverTimeline mismatch") + } }) - }) -}) + } +} func reconcileAndAssertState(ctx context.Context, nn types.NamespacedName, cr *v2.PerconaPGCluster, expectedState v2.AppState) { _, err := reconciler(cr).Reconcile(ctx, ctrl.Request{NamespacedName: nn}) From 86b92455aa9dcb826b95d1aaf72d7520721ec7d5 Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 17 Feb 2026 13:53:11 +0100 Subject: [PATCH 299/300] K8SPG-647 separate major upgrade test --- e2e-tests/functions | 4 +- .../00-assert.yaml | 0 .../00-deploy-operator.yaml | 0 .../01-assert.yaml | 24 ++-- .../01-create-cluster.yaml | 0 .../02-write-data.yaml | 8 +- .../03-assert.yaml | 0 .../03-read-from-primary.yaml | 4 +- .../04-assert.yaml | 4 +- .../04-upgrade.yaml} | 3 +- .../05-assert.yaml | 4 +- .../05-change-repo.yaml | 2 +- .../06-assert.yaml | 2 +- .../06-run-backup.yaml | 2 +- .../07-assert.yaml | 0 .../07-read-from-primary.yaml | 4 +- .../99-remove-cluster-gracefully.yaml | 4 +- .../major-upgrade-14-to-15/00-assert.yaml | 24 ++++ .../00-deploy-operator.yaml | 14 ++ .../major-upgrade-14-to-15/01-assert.yaml | 135 ++++++++++++++++++ .../01-create-cluster.yaml | 20 +++ .../major-upgrade-14-to-15/02-write-data.yaml | 20 +++ .../03-assert.yaml} | 2 +- .../03-read-from-primary.yaml} | 4 +- .../04-assert.yaml} | 6 +- .../04-upgrade.yaml} | 3 +- .../05-assert.yaml} | 6 +- .../05-change-repo.yaml} | 4 +- .../06-assert.yaml} | 6 +- .../06-run-backup.yaml} | 4 +- .../07-assert.yaml} | 2 +- .../07-read-from-primary.yaml} | 4 +- .../99-remove-cluster-gracefully.yaml | 21 +++ .../major-upgrade-15-to-16/00-assert.yaml | 24 ++++ .../00-deploy-operator.yaml | 14 ++ .../major-upgrade-15-to-16/01-assert.yaml | 135 ++++++++++++++++++ .../01-create-cluster.yaml | 20 +++ .../major-upgrade-15-to-16/02-write-data.yaml | 20 +++ .../03-assert.yaml} | 2 +- .../03-read-from-primary.yaml | 12 ++ .../04-assert.yaml} | 6 +- .../04-upgrade.yaml} | 3 +- .../05-assert.yaml} | 6 +- .../05-change-repo.yaml} | 4 +- .../06-assert.yaml} | 6 +- .../06-run-backup.yaml} | 4 +- .../07-assert.yaml} | 2 +- .../07-read-from-primary.yaml | 12 ++ .../99-remove-cluster-gracefully.yaml | 21 +++ .../major-upgrade-16-to-17/00-assert.yaml | 24 ++++ .../00-deploy-operator.yaml | 14 ++ .../major-upgrade-16-to-17/01-assert.yaml | 135 ++++++++++++++++++ .../01-create-cluster.yaml | 20 +++ .../major-upgrade-16-to-17/02-write-data.yaml | 20 +++ .../major-upgrade-16-to-17/03-assert.yaml | 10 ++ .../03-read-from-primary.yaml | 12 ++ .../04-assert.yaml} | 6 +- .../04-upgrade.yaml} | 3 +- .../05-assert.yaml} | 6 +- .../05-change-repo.yaml | 12 ++ .../06-assert.yaml} | 6 +- .../06-run-backup.yaml} | 4 +- .../major-upgrade-16-to-17/07-assert.yaml | 10 ++ .../07-read-from-primary.yaml | 12 ++ .../99-remove-cluster-gracefully.yaml | 21 +++ .../major-upgrade-17-to-18/00-assert.yaml | 24 ++++ .../00-deploy-operator.yaml | 14 ++ .../major-upgrade-17-to-18/01-assert.yaml | 135 ++++++++++++++++++ .../01-create-cluster.yaml | 20 +++ .../major-upgrade-17-to-18/02-write-data.yaml | 20 +++ .../major-upgrade-17-to-18/03-assert.yaml | 10 ++ .../03-read-from-primary.yaml | 12 ++ .../04-assert.yaml} | 6 +- .../04-upgrade.yaml} | 3 +- .../major-upgrade-17-to-18/05-assert.yaml | 21 +++ .../05-change-repo.yaml | 12 ++ .../06-assert.yaml} | 6 +- .../06-run-backup.yaml} | 4 +- .../major-upgrade-17-to-18/07-assert.yaml | 10 ++ .../07-read-from-primary.yaml | 12 ++ .../99-remove-cluster-gracefully.yaml | 21 +++ .../major-upgrade/11-read-from-primary.yaml | 12 -- .../major-upgrade/15-read-from-primary.yaml | 12 -- e2e-tests/tests/major-upgrade/21-assert.yaml | 21 --- 84 files changed, 1182 insertions(+), 139 deletions(-) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/00-assert.yaml (100%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/00-deploy-operator.yaml (100%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/01-assert.yaml (83%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/01-create-cluster.yaml (100%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/02-write-data.yaml (50%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/03-assert.yaml (100%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/03-read-from-primary.yaml (62%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/04-assert.yaml (88%) rename e2e-tests/tests/{major-upgrade/04-13-to-14.yaml => major-upgrade-13-to-14/04-upgrade.yaml} (92%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/05-assert.yaml (81%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/05-change-repo.yaml (84%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/06-assert.yaml (94%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/06-run-backup.yaml (80%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/07-assert.yaml (100%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/07-read-from-primary.yaml (62%) rename e2e-tests/tests/{major-upgrade => major-upgrade-13-to-14}/99-remove-cluster-gracefully.yaml (85%) create mode 100644 e2e-tests/tests/major-upgrade-14-to-15/00-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-14-to-15/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/major-upgrade-14-to-15/01-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-14-to-15/01-create-cluster.yaml create mode 100644 e2e-tests/tests/major-upgrade-14-to-15/02-write-data.yaml rename e2e-tests/tests/{major-upgrade/15-assert.yaml => major-upgrade-14-to-15/03-assert.yaml} (81%) rename e2e-tests/tests/{major-upgrade/19-read-from-primary.yaml => major-upgrade-14-to-15/03-read-from-primary.yaml} (56%) rename e2e-tests/tests/{major-upgrade/08-assert.yaml => major-upgrade-14-to-15/04-assert.yaml} (82%) rename e2e-tests/tests/{major-upgrade/08-14-to-15.yaml => major-upgrade-14-to-15/04-upgrade.yaml} (92%) rename e2e-tests/tests/{major-upgrade/09-assert.yaml => major-upgrade-14-to-15/05-assert.yaml} (77%) rename e2e-tests/tests/{major-upgrade/09-change-repo.yaml => major-upgrade-14-to-15/05-change-repo.yaml} (74%) rename e2e-tests/tests/{major-upgrade/10-assert.yaml => major-upgrade-14-to-15/06-assert.yaml} (83%) rename e2e-tests/tests/{major-upgrade/10-run-backup.yaml => major-upgrade-14-to-15/06-run-backup.yaml} (70%) rename e2e-tests/tests/{major-upgrade/19-assert.yaml => major-upgrade-14-to-15/07-assert.yaml} (81%) rename e2e-tests/tests/{major-upgrade/23-read-from-primary.yaml => major-upgrade-14-to-15/07-read-from-primary.yaml} (56%) create mode 100644 e2e-tests/tests/major-upgrade-14-to-15/99-remove-cluster-gracefully.yaml create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/00-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/01-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/01-create-cluster.yaml create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/02-write-data.yaml rename e2e-tests/tests/{major-upgrade/11-assert.yaml => major-upgrade-15-to-16/03-assert.yaml} (81%) create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/03-read-from-primary.yaml rename e2e-tests/tests/{major-upgrade/12-assert.yaml => major-upgrade-15-to-16/04-assert.yaml} (82%) rename e2e-tests/tests/{major-upgrade/12-15-to-16.yaml => major-upgrade-15-to-16/04-upgrade.yaml} (92%) rename e2e-tests/tests/{major-upgrade/13-assert.yaml => major-upgrade-15-to-16/05-assert.yaml} (77%) rename e2e-tests/tests/{major-upgrade/13-change-repo.yaml => major-upgrade-15-to-16/05-change-repo.yaml} (74%) rename e2e-tests/tests/{major-upgrade/14-assert.yaml => major-upgrade-15-to-16/06-assert.yaml} (83%) rename e2e-tests/tests/{major-upgrade/14-run-backup.yaml => major-upgrade-15-to-16/06-run-backup.yaml} (70%) rename e2e-tests/tests/{major-upgrade/23-assert.yaml => major-upgrade-15-to-16/07-assert.yaml} (81%) create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/07-read-from-primary.yaml create mode 100644 e2e-tests/tests/major-upgrade-15-to-16/99-remove-cluster-gracefully.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/00-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/01-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/01-create-cluster.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/02-write-data.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/03-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/03-read-from-primary.yaml rename e2e-tests/tests/{major-upgrade/16-assert.yaml => major-upgrade-16-to-17/04-assert.yaml} (82%) rename e2e-tests/tests/{major-upgrade/16-16-to-17.yaml => major-upgrade-16-to-17/04-upgrade.yaml} (92%) rename e2e-tests/tests/{major-upgrade/17-assert.yaml => major-upgrade-16-to-17/05-assert.yaml} (77%) create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/05-change-repo.yaml rename e2e-tests/tests/{major-upgrade/18-assert.yaml => major-upgrade-16-to-17/06-assert.yaml} (83%) rename e2e-tests/tests/{major-upgrade/18-run-backup.yaml => major-upgrade-16-to-17/06-run-backup.yaml} (70%) create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/07-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/07-read-from-primary.yaml create mode 100644 e2e-tests/tests/major-upgrade-16-to-17/99-remove-cluster-gracefully.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/00-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/00-deploy-operator.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/01-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/01-create-cluster.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/02-write-data.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/03-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/03-read-from-primary.yaml rename e2e-tests/tests/{major-upgrade/20-assert.yaml => major-upgrade-17-to-18/04-assert.yaml} (82%) rename e2e-tests/tests/{major-upgrade/20-17-to-18.yaml => major-upgrade-17-to-18/04-upgrade.yaml} (92%) create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/05-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/05-change-repo.yaml rename e2e-tests/tests/{major-upgrade/22-assert.yaml => major-upgrade-17-to-18/06-assert.yaml} (83%) rename e2e-tests/tests/{major-upgrade/22-run-backup.yaml => major-upgrade-17-to-18/06-run-backup.yaml} (70%) create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/07-assert.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/07-read-from-primary.yaml create mode 100644 e2e-tests/tests/major-upgrade-17-to-18/99-remove-cluster-gracefully.yaml delete mode 100644 e2e-tests/tests/major-upgrade/11-read-from-primary.yaml delete mode 100644 e2e-tests/tests/major-upgrade/15-read-from-primary.yaml delete mode 100644 e2e-tests/tests/major-upgrade/21-assert.yaml diff --git a/e2e-tests/functions b/e2e-tests/functions index b35c245479..9061a90acc 100644 --- a/e2e-tests/functions +++ b/e2e-tests/functions @@ -256,7 +256,7 @@ deploy_s3_secrets() { yq eval '.stringData["credentials.json"]' ${TESTS_CONFIG_DIR}/cloud-secret-minio-gw.yml >${TEMP_DIR}/gcs-key.json kubectl -n "${NAMESPACE}" create secret generic "${test_name}-pgbackrest-secrets" --from-file=cloud.conf="${TEMP_DIR}/pgbackrest-secret.ini" --from-file=gcs-key.json=${TEMP_DIR}/gcs-key.json ;; - "custom-extensions" | "major-upgrade" | "builtin-extensions") + "custom-extensions"| "builtin-extensions"| major-upgrade*) kubectl -n "${NAMESPACE}" apply -f "${TESTS_CONFIG_DIR}/cloud-secret.yml" kubectl -n "${NAMESPACE}" apply -f "${TESTS_CONFIG_DIR}/minio-secret.yml" ;; @@ -341,7 +341,7 @@ get_cr() { .spec.backups.pgbackrest.repos += [{"name":"repo3","azure":{"container":"'$BUCKET'"}}] ' $TEMP_DIR/cr.yaml ;; - "major-upgrade") + major-upgrade*) yq eval -i ' .spec.extensions.image = "'$IMAGE'" | .spec.extensions.imagePullPolicy = "Always" | diff --git a/e2e-tests/tests/major-upgrade/00-assert.yaml b/e2e-tests/tests/major-upgrade-13-to-14/00-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/00-assert.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/00-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/00-deploy-operator.yaml b/e2e-tests/tests/major-upgrade-13-to-14/00-deploy-operator.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/00-deploy-operator.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/00-deploy-operator.yaml diff --git a/e2e-tests/tests/major-upgrade/01-assert.yaml b/e2e-tests/tests/major-upgrade-13-to-14/01-assert.yaml similarity index 83% rename from e2e-tests/tests/major-upgrade/01-assert.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/01-assert.yaml index 8fee6151e6..80089a9b48 100644 --- a/e2e-tests/tests/major-upgrade/01-assert.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/01-assert.yaml @@ -5,16 +5,16 @@ timeout: 120 kind: StatefulSet apiVersion: apps/v1 metadata: - name: major-upgrade-repo-host + name: major-upgrade-13-to-14-repo-host labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-13-to-14 postgres-operator.crunchydata.com/data: pgbackrest postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-dedicated: '' ownerReferences: - apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster - name: major-upgrade + name: major-upgrade-13-to-14 controller: true blockOwnerDeletion: true status: @@ -29,13 +29,13 @@ kind: StatefulSet apiVersion: apps/v1 metadata: labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-13-to-14 postgres-operator.crunchydata.com/data: postgres postgres-operator.crunchydata.com/instance-set: instance1 ownerReferences: - apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster - name: major-upgrade + name: major-upgrade-13-to-14 controller: true blockOwnerDeletion: true status: @@ -49,16 +49,16 @@ status: kind: Deployment apiVersion: apps/v1 metadata: - name: major-upgrade-pgbouncer + name: major-upgrade-13-to-14-pgbouncer labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-13-to-14 postgres-operator.crunchydata.com/role: pgbouncer annotations: deployment.kubernetes.io/revision: '1' ownerReferences: - apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster - name: major-upgrade + name: major-upgrade-13-to-14 controller: true blockOwnerDeletion: true status: @@ -71,7 +71,7 @@ kind: Job apiVersion: batch/v1 metadata: labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-13-to-14 postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create postgres-operator.crunchydata.com/pgbackrest-repo: repo1 @@ -86,11 +86,11 @@ status: apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: - name: major-upgrade + name: major-upgrade-13-to-14 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster - name: major-upgrade + name: major-upgrade-13-to-14 controller: true blockOwnerDeletion: true finalizers: @@ -120,7 +120,7 @@ status: apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: major-upgrade + name: major-upgrade-13-to-14 status: pgbouncer: ready: 3 diff --git a/e2e-tests/tests/major-upgrade/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade-13-to-14/01-create-cluster.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/01-create-cluster.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/01-create-cluster.yaml diff --git a/e2e-tests/tests/major-upgrade/02-write-data.yaml b/e2e-tests/tests/major-upgrade-13-to-14/02-write-data.yaml similarity index 50% rename from e2e-tests/tests/major-upgrade/02-write-data.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/02-write-data.yaml index da5b97f2a7..03ebd9ca7f 100644 --- a/e2e-tests/tests/major-upgrade/02-write-data.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/02-write-data.yaml @@ -9,12 +9,12 @@ commands: run_psql_local \ 'CREATE DATABASE myapp; \c myapp \\\ CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY);' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" - + "postgres:$(get_psql_user_pass major-upgrade-13-to-14-pguser-postgres)@$(get_psql_user_host major-upgrade-13-to-14-pguser-postgres)" + run_psql_local \ '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" + "postgres:$(get_psql_user_pass major-upgrade-13-to-14-pguser-postgres)@$(get_psql_user_host major-upgrade-13-to-14-pguser-postgres)" run_psql_local \ '\c postgres \\\ CREATE EXTENSION pg_cron' \ - "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)" \ No newline at end of file + "postgres:$(get_psql_user_pass major-upgrade-13-to-14-pguser-postgres)@$(get_psql_user_host major-upgrade-13-to-14-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/03-assert.yaml b/e2e-tests/tests/major-upgrade-13-to-14/03-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/03-assert.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/03-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/03-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-13-to-14/03-read-from-primary.yaml similarity index 62% rename from e2e-tests/tests/major-upgrade/03-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/03-read-from-primary.yaml index 64ad0782ac..c22c680791 100644 --- a/e2e-tests/tests/major-upgrade/03-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/03-read-from-primary.yaml @@ -7,6 +7,6 @@ commands: set -o xtrace source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-13-to-14-pguser-postgres)@$(get_psql_user_host major-upgrade-13-to-14-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 03-read-from-primary --from-literal=data="${data}" \ No newline at end of file + kubectl create configmap -n "${NAMESPACE}" 03-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/04-assert.yaml b/e2e-tests/tests/major-upgrade-13-to-14/04-assert.yaml similarity index 88% rename from e2e-tests/tests/major-upgrade/04-assert.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/04-assert.yaml index 23d3a30f61..2deb12c5ad 100644 --- a/e2e-tests/tests/major-upgrade/04-assert.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/04-assert.yaml @@ -9,7 +9,7 @@ commands: apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: major-upgrade + name: major-upgrade-13-to-14 spec: postgresVersion: 14 status: @@ -29,7 +29,7 @@ kind: Job apiVersion: batch/v1 metadata: labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-13-to-14 postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create postgres-operator.crunchydata.com/pgbackrest-repo: repo1 diff --git a/e2e-tests/tests/major-upgrade/04-13-to-14.yaml b/e2e-tests/tests/major-upgrade-13-to-14/04-upgrade.yaml similarity index 92% rename from e2e-tests/tests/major-upgrade/04-13-to-14.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/04-upgrade.yaml index c3c4e9c3c2..a8cf9ea308 100644 --- a/e2e-tests/tests/major-upgrade/04-13-to-14.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/04-upgrade.yaml @@ -13,7 +13,7 @@ commands: metadata: name: 13-to-14 spec: - postgresClusterName: major-upgrade + postgresClusterName: major-upgrade-13-to-14 image: ${IMAGE_UPGRADE} fromPostgresVersion: 13 toPostgresVersion: 14 @@ -21,4 +21,3 @@ commands: toPgBouncerImage: $(get_container_image "pgbouncer" 14) toPgBackRestImage: $(get_container_image "pgbackrest" 14) EOF - diff --git a/e2e-tests/tests/major-upgrade/05-assert.yaml b/e2e-tests/tests/major-upgrade-13-to-14/05-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/05-assert.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/05-assert.yaml index 47ccba03b5..82c9a205bb 100644 --- a/e2e-tests/tests/major-upgrade/05-assert.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/05-assert.yaml @@ -3,7 +3,7 @@ kind: TestAssert timeout: 660 commands: - script: |- - kubectl get postgrescluster major-upgrade \ + kubectl get postgrescluster major-upgrade-13-to-14 \ -n ${NAMESPACE} \ -o yaml \ | yq eval '.status.pgbackrest.repos' - @@ -11,7 +11,7 @@ commands: apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: - name: major-upgrade + name: major-upgrade-13-to-14 status: pgbackrest: repos: diff --git a/e2e-tests/tests/major-upgrade/05-change-repo.yaml b/e2e-tests/tests/major-upgrade-13-to-14/05-change-repo.yaml similarity index 84% rename from e2e-tests/tests/major-upgrade/05-change-repo.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/05-change-repo.yaml index 22094b19f4..8ad979572a 100644 --- a/e2e-tests/tests/major-upgrade/05-change-repo.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/05-change-repo.yaml @@ -7,6 +7,6 @@ commands: kubectl patch \ -n $NAMESPACE \ - perconapgcluster major-upgrade \ + perconapgcluster major-upgrade-13-to-14 \ --type='json' \ -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo2"}]' diff --git a/e2e-tests/tests/major-upgrade/06-assert.yaml b/e2e-tests/tests/major-upgrade-13-to-14/06-assert.yaml similarity index 94% rename from e2e-tests/tests/major-upgrade/06-assert.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/06-assert.yaml index 605465e35a..6b9030f712 100644 --- a/e2e-tests/tests/major-upgrade/06-assert.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/06-assert.yaml @@ -23,7 +23,7 @@ kind: PerconaPGBackup metadata: name: backup-after-13-to-14 spec: - pgCluster: major-upgrade + pgCluster: major-upgrade-13-to-14 repoName: repo2 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/06-run-backup.yaml b/e2e-tests/tests/major-upgrade-13-to-14/06-run-backup.yaml similarity index 80% rename from e2e-tests/tests/major-upgrade/06-run-backup.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/06-run-backup.yaml index aaf7d5a7c4..b16847144d 100644 --- a/e2e-tests/tests/major-upgrade/06-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/06-run-backup.yaml @@ -3,7 +3,7 @@ kind: PerconaPGBackup metadata: name: backup-after-13-to-14 spec: - pgCluster: major-upgrade + pgCluster: major-upgrade-13-to-14 repoName: repo2 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/07-assert.yaml b/e2e-tests/tests/major-upgrade-13-to-14/07-assert.yaml similarity index 100% rename from e2e-tests/tests/major-upgrade/07-assert.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/07-assert.yaml diff --git a/e2e-tests/tests/major-upgrade/07-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-13-to-14/07-read-from-primary.yaml similarity index 62% rename from e2e-tests/tests/major-upgrade/07-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/07-read-from-primary.yaml index bfa5e93458..db16d050e6 100644 --- a/e2e-tests/tests/major-upgrade/07-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/07-read-from-primary.yaml @@ -7,6 +7,6 @@ commands: set -o xtrace source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-13-to-14-pguser-postgres)@$(get_psql_user_host major-upgrade-13-to-14-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 07-read-from-primary --from-literal=data="${data}" \ No newline at end of file + kubectl create configmap -n "${NAMESPACE}" 07-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/major-upgrade-13-to-14/99-remove-cluster-gracefully.yaml similarity index 85% rename from e2e-tests/tests/major-upgrade/99-remove-cluster-gracefully.yaml rename to e2e-tests/tests/major-upgrade-13-to-14/99-remove-cluster-gracefully.yaml index dd7090425b..6b3655e153 100644 --- a/e2e-tests/tests/major-upgrade/99-remove-cluster-gracefully.yaml +++ b/e2e-tests/tests/major-upgrade-13-to-14/99-remove-cluster-gracefully.yaml @@ -4,11 +4,11 @@ delete: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: major-upgrade + name: major-upgrade-13-to-14 - apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: - name: major-upgrade + name: major-upgrade-13-to-14 commands: - script: |- set -o errexit diff --git a/e2e-tests/tests/major-upgrade-14-to-15/00-assert.yaml b/e2e-tests/tests/major-upgrade-14-to-15/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-14-to-15/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/major-upgrade-14-to-15/00-deploy-operator.yaml b/e2e-tests/tests/major-upgrade-14-to-15/00-deploy-operator.yaml new file mode 100644 index 0000000000..7faf4da852 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-14-to-15/00-deploy-operator.yaml @@ -0,0 +1,14 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client + deploy_s3_secrets diff --git a/e2e-tests/tests/major-upgrade-14-to-15/01-assert.yaml b/e2e-tests/tests/major-upgrade-14-to-15/01-assert.yaml new file mode 100644 index 0000000000..c97a6fde94 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-14-to-15/01-assert.yaml @@ -0,0 +1,135 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: major-upgrade-14-to-15-repo-host + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-14-to-15 + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-14-to-15 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-14-to-15 + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-14-to-15 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: major-upgrade-14-to-15-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-14-to-15 + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-14-to-15 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-14-to-15 + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: major-upgrade-14-to-15 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: major-upgrade-14-to-15 + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: major-upgrade-14-to-15 +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/major-upgrade-14-to-15/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade-14-to-15/01-create-cluster.yaml new file mode 100644 index 0000000000..8b58c0ae9d --- /dev/null +++ b/e2e-tests/tests/major-upgrade-14-to-15/01-create-cluster.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr \ + | yq eval ' + .spec.postgresVersion = 14 | + .spec.image = "perconalab/percona-postgresql-operator:main-ppg14-postgres" | + .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | + .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-pgbouncer14" | + .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-pgbackrest14" | + .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | + .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.6"}]' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade-14-to-15/02-write-data.yaml b/e2e-tests/tests/major-upgrade-14-to-15/02-write-data.yaml new file mode 100644 index 0000000000..e1c42894cd --- /dev/null +++ b/e2e-tests/tests/major-upgrade-14-to-15/02-write-data.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'CREATE DATABASE myapp; \c myapp \\\ CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY);' \ + "postgres:$(get_psql_user_pass major-upgrade-14-to-15-pguser-postgres)@$(get_psql_user_host major-upgrade-14-to-15-pguser-postgres)" + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ + "postgres:$(get_psql_user_pass major-upgrade-14-to-15-pguser-postgres)@$(get_psql_user_host major-upgrade-14-to-15-pguser-postgres)" + + run_psql_local \ + '\c postgres \\\ CREATE EXTENSION pg_cron' \ + "postgres:$(get_psql_user_pass major-upgrade-14-to-15-pguser-postgres)@$(get_psql_user_host major-upgrade-14-to-15-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/15-assert.yaml b/e2e-tests/tests/major-upgrade-14-to-15/03-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/15-assert.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/03-assert.yaml index 3590bbe99a..6848a5b79a 100644 --- a/e2e-tests/tests/major-upgrade/15-assert.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/03-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 15-read-from-primary + name: 03-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-14-to-15/03-read-from-primary.yaml similarity index 56% rename from e2e-tests/tests/major-upgrade/19-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/03-read-from-primary.yaml index f835a311f5..f433ebb388 100644 --- a/e2e-tests/tests/major-upgrade/19-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/03-read-from-primary.yaml @@ -7,6 +7,6 @@ commands: set -o xtrace source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-14-to-15-pguser-postgres)@$(get_psql_user_host major-upgrade-14-to-15-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 19-read-from-primary --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 03-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/08-assert.yaml b/e2e-tests/tests/major-upgrade-14-to-15/04-assert.yaml similarity index 82% rename from e2e-tests/tests/major-upgrade/08-assert.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/04-assert.yaml index c00e35e2ae..a331300b0e 100644 --- a/e2e-tests/tests/major-upgrade/08-assert.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/04-assert.yaml @@ -9,7 +9,7 @@ commands: apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: major-upgrade + name: major-upgrade-14-to-15 spec: postgresVersion: 15 status: @@ -29,10 +29,10 @@ kind: Job apiVersion: batch/v1 metadata: labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-14-to-15 postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo2 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/08-14-to-15.yaml b/e2e-tests/tests/major-upgrade-14-to-15/04-upgrade.yaml similarity index 92% rename from e2e-tests/tests/major-upgrade/08-14-to-15.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/04-upgrade.yaml index 537582d6ad..72597913bd 100644 --- a/e2e-tests/tests/major-upgrade/08-14-to-15.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/04-upgrade.yaml @@ -13,7 +13,7 @@ commands: metadata: name: 14-to-15 spec: - postgresClusterName: major-upgrade + postgresClusterName: major-upgrade-14-to-15 image: ${IMAGE_UPGRADE} fromPostgresVersion: 14 toPostgresVersion: 15 @@ -21,4 +21,3 @@ commands: toPgBouncerImage: $(get_container_image "pgbouncer" 15) toPgBackRestImage: $(get_container_image "pgbackrest" 15) EOF - diff --git a/e2e-tests/tests/major-upgrade/09-assert.yaml b/e2e-tests/tests/major-upgrade-14-to-15/05-assert.yaml similarity index 77% rename from e2e-tests/tests/major-upgrade/09-assert.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/05-assert.yaml index 301240b0f5..5de286a47f 100644 --- a/e2e-tests/tests/major-upgrade/09-assert.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/05-assert.yaml @@ -3,7 +3,7 @@ kind: TestAssert timeout: 660 commands: - script: |- - kubectl get postgrescluster major-upgrade \ + kubectl get postgrescluster major-upgrade-14-to-15 \ -n ${NAMESPACE} \ -o yaml \ | yq eval '.status.pgbackrest.repos' - @@ -11,11 +11,11 @@ commands: apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: - name: major-upgrade + name: major-upgrade-14-to-15 status: pgbackrest: repos: - bound: true - name: repo3 + name: repo2 replicaCreateBackupComplete: true stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/09-change-repo.yaml b/e2e-tests/tests/major-upgrade-14-to-15/05-change-repo.yaml similarity index 74% rename from e2e-tests/tests/major-upgrade/09-change-repo.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/05-change-repo.yaml index 57f9edc8a4..fb07adda88 100644 --- a/e2e-tests/tests/major-upgrade/09-change-repo.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/05-change-repo.yaml @@ -7,6 +7,6 @@ commands: kubectl patch \ -n $NAMESPACE \ - perconapgcluster major-upgrade \ + perconapgcluster major-upgrade-14-to-15 \ --type='json' \ - -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo3"}]' + -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo2"}]' diff --git a/e2e-tests/tests/major-upgrade/10-assert.yaml b/e2e-tests/tests/major-upgrade-14-to-15/06-assert.yaml similarity index 83% rename from e2e-tests/tests/major-upgrade/10-assert.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/06-assert.yaml index 4a603ba7e9..e81a8627e6 100644 --- a/e2e-tests/tests/major-upgrade/10-assert.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/06-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-14-to-15 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo3 + postgres-operator.crunchydata.com/pgbackrest-repo: repo2 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -23,8 +23,8 @@ kind: PerconaPGBackup metadata: name: backup-after-14-to-15 spec: - pgCluster: major-upgrade - repoName: repo3 + pgCluster: major-upgrade-14-to-15 + repoName: repo2 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/10-run-backup.yaml b/e2e-tests/tests/major-upgrade-14-to-15/06-run-backup.yaml similarity index 70% rename from e2e-tests/tests/major-upgrade/10-run-backup.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/06-run-backup.yaml index 047e0b5571..5cf7a37918 100644 --- a/e2e-tests/tests/major-upgrade/10-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/06-run-backup.yaml @@ -3,7 +3,7 @@ kind: PerconaPGBackup metadata: name: backup-after-14-to-15 spec: - pgCluster: major-upgrade - repoName: repo3 + pgCluster: major-upgrade-14-to-15 + repoName: repo2 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/19-assert.yaml b/e2e-tests/tests/major-upgrade-14-to-15/07-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/19-assert.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/07-assert.yaml index 381403d405..c86dbb55fc 100644 --- a/e2e-tests/tests/major-upgrade/19-assert.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/07-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 19-read-from-primary + name: 07-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade/23-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-14-to-15/07-read-from-primary.yaml similarity index 56% rename from e2e-tests/tests/major-upgrade/23-read-from-primary.yaml rename to e2e-tests/tests/major-upgrade-14-to-15/07-read-from-primary.yaml index 48798197b8..23286b08fd 100644 --- a/e2e-tests/tests/major-upgrade/23-read-from-primary.yaml +++ b/e2e-tests/tests/major-upgrade-14-to-15/07-read-from-primary.yaml @@ -7,6 +7,6 @@ commands: set -o xtrace source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-14-to-15-pguser-postgres)@$(get_psql_user_host major-upgrade-14-to-15-pguser-postgres)") - kubectl create configmap -n "${NAMESPACE}" 23-read-from-primary --from-literal=data="${data}" + kubectl create configmap -n "${NAMESPACE}" 07-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade-14-to-15/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/major-upgrade-14-to-15/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..32e0c48cd2 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-14-to-15/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: major-upgrade-14-to-15 +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: major-upgrade-14-to-15 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 diff --git a/e2e-tests/tests/major-upgrade-15-to-16/00-assert.yaml b/e2e-tests/tests/major-upgrade-15-to-16/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/major-upgrade-15-to-16/00-deploy-operator.yaml b/e2e-tests/tests/major-upgrade-15-to-16/00-deploy-operator.yaml new file mode 100644 index 0000000000..7faf4da852 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/00-deploy-operator.yaml @@ -0,0 +1,14 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client + deploy_s3_secrets diff --git a/e2e-tests/tests/major-upgrade-15-to-16/01-assert.yaml b/e2e-tests/tests/major-upgrade-15-to-16/01-assert.yaml new file mode 100644 index 0000000000..182f2a5392 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/01-assert.yaml @@ -0,0 +1,135 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: major-upgrade-15-to-16-repo-host + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-15-to-16 + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-15-to-16 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-15-to-16 + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-15-to-16 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: major-upgrade-15-to-16-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-15-to-16 + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-15-to-16 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-15-to-16 + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: major-upgrade-15-to-16 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: major-upgrade-15-to-16 + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: major-upgrade-15-to-16 +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/major-upgrade-15-to-16/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade-15-to-16/01-create-cluster.yaml new file mode 100644 index 0000000000..cc8b3ccd0d --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/01-create-cluster.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr \ + | yq eval ' + .spec.postgresVersion = 15 | + .spec.image = "perconalab/percona-postgresql-operator:main-ppg15-postgres" | + .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | + .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-pgbouncer15" | + .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-pgbackrest15" | + .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | + .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.6"}]' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade-15-to-16/02-write-data.yaml b/e2e-tests/tests/major-upgrade-15-to-16/02-write-data.yaml new file mode 100644 index 0000000000..114a236893 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/02-write-data.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'CREATE DATABASE myapp; \c myapp \\\ CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY);' \ + "postgres:$(get_psql_user_pass major-upgrade-15-to-16-pguser-postgres)@$(get_psql_user_host major-upgrade-15-to-16-pguser-postgres)" + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ + "postgres:$(get_psql_user_pass major-upgrade-15-to-16-pguser-postgres)@$(get_psql_user_host major-upgrade-15-to-16-pguser-postgres)" + + run_psql_local \ + '\c postgres \\\ CREATE EXTENSION pg_cron' \ + "postgres:$(get_psql_user_pass major-upgrade-15-to-16-pguser-postgres)@$(get_psql_user_host major-upgrade-15-to-16-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade/11-assert.yaml b/e2e-tests/tests/major-upgrade-15-to-16/03-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/11-assert.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/03-assert.yaml index 95d57c293f..6848a5b79a 100644 --- a/e2e-tests/tests/major-upgrade/11-assert.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/03-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 11-read-from-primary + name: 03-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade-15-to-16/03-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-15-to-16/03-read-from-primary.yaml new file mode 100644 index 0000000000..eb24c35010 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/03-read-from-primary.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-15-to-16-pguser-postgres)@$(get_psql_user_host major-upgrade-15-to-16-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 03-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/12-assert.yaml b/e2e-tests/tests/major-upgrade-15-to-16/04-assert.yaml similarity index 82% rename from e2e-tests/tests/major-upgrade/12-assert.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/04-assert.yaml index 8cd5dbcad3..3ef4fd852f 100644 --- a/e2e-tests/tests/major-upgrade/12-assert.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/04-assert.yaml @@ -9,7 +9,7 @@ commands: apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: major-upgrade + name: major-upgrade-15-to-16 spec: postgresVersion: 16 status: @@ -29,10 +29,10 @@ kind: Job apiVersion: batch/v1 metadata: labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-15-to-16 postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo3 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/12-15-to-16.yaml b/e2e-tests/tests/major-upgrade-15-to-16/04-upgrade.yaml similarity index 92% rename from e2e-tests/tests/major-upgrade/12-15-to-16.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/04-upgrade.yaml index 994831051c..57936b66bb 100644 --- a/e2e-tests/tests/major-upgrade/12-15-to-16.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/04-upgrade.yaml @@ -13,7 +13,7 @@ commands: metadata: name: 15-to-16 spec: - postgresClusterName: major-upgrade + postgresClusterName: major-upgrade-15-to-16 image: ${IMAGE_UPGRADE} fromPostgresVersion: 15 toPostgresVersion: 16 @@ -21,4 +21,3 @@ commands: toPgBouncerImage: $(get_container_image "pgbouncer" 16) toPgBackRestImage: $(get_container_image "pgbackrest" 16) EOF - diff --git a/e2e-tests/tests/major-upgrade/13-assert.yaml b/e2e-tests/tests/major-upgrade-15-to-16/05-assert.yaml similarity index 77% rename from e2e-tests/tests/major-upgrade/13-assert.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/05-assert.yaml index 6af985e4b7..efef66ec9d 100644 --- a/e2e-tests/tests/major-upgrade/13-assert.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/05-assert.yaml @@ -3,7 +3,7 @@ kind: TestAssert timeout: 660 commands: - script: |- - kubectl get postgrescluster major-upgrade \ + kubectl get postgrescluster major-upgrade-15-to-16 \ -n ${NAMESPACE} \ -o yaml \ | yq eval '.status.pgbackrest.repos' - @@ -11,11 +11,11 @@ commands: apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: - name: major-upgrade + name: major-upgrade-15-to-16 status: pgbackrest: repos: - bound: true - name: repo4 + name: repo2 replicaCreateBackupComplete: true stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade/13-change-repo.yaml b/e2e-tests/tests/major-upgrade-15-to-16/05-change-repo.yaml similarity index 74% rename from e2e-tests/tests/major-upgrade/13-change-repo.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/05-change-repo.yaml index 33711377c4..817f320a6f 100644 --- a/e2e-tests/tests/major-upgrade/13-change-repo.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/05-change-repo.yaml @@ -7,6 +7,6 @@ commands: kubectl patch \ -n $NAMESPACE \ - perconapgcluster major-upgrade \ + perconapgcluster major-upgrade-15-to-16 \ --type='json' \ - -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo4"}]' + -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo2"}]' diff --git a/e2e-tests/tests/major-upgrade/14-assert.yaml b/e2e-tests/tests/major-upgrade-15-to-16/06-assert.yaml similarity index 83% rename from e2e-tests/tests/major-upgrade/14-assert.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/06-assert.yaml index 55610fcd16..6561bdcf39 100644 --- a/e2e-tests/tests/major-upgrade/14-assert.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/06-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-15-to-16 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo2 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -23,8 +23,8 @@ kind: PerconaPGBackup metadata: name: backup-after-15-to-16 spec: - pgCluster: major-upgrade - repoName: repo4 + pgCluster: major-upgrade-15-to-16 + repoName: repo2 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/14-run-backup.yaml b/e2e-tests/tests/major-upgrade-15-to-16/06-run-backup.yaml similarity index 70% rename from e2e-tests/tests/major-upgrade/14-run-backup.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/06-run-backup.yaml index adc6c49ed2..bebfdfcb61 100644 --- a/e2e-tests/tests/major-upgrade/14-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/06-run-backup.yaml @@ -3,7 +3,7 @@ kind: PerconaPGBackup metadata: name: backup-after-15-to-16 spec: - pgCluster: major-upgrade - repoName: repo4 + pgCluster: major-upgrade-15-to-16 + repoName: repo2 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade/23-assert.yaml b/e2e-tests/tests/major-upgrade-15-to-16/07-assert.yaml similarity index 81% rename from e2e-tests/tests/major-upgrade/23-assert.yaml rename to e2e-tests/tests/major-upgrade-15-to-16/07-assert.yaml index 15c83197aa..c86dbb55fc 100644 --- a/e2e-tests/tests/major-upgrade/23-assert.yaml +++ b/e2e-tests/tests/major-upgrade-15-to-16/07-assert.yaml @@ -5,6 +5,6 @@ timeout: 30 kind: ConfigMap apiVersion: v1 metadata: - name: 23-read-from-primary + name: 07-read-from-primary data: data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade-15-to-16/07-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-15-to-16/07-read-from-primary.yaml new file mode 100644 index 0000000000..a72c82c3b7 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/07-read-from-primary.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-15-to-16-pguser-postgres)@$(get_psql_user_host major-upgrade-15-to-16-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 07-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade-15-to-16/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/major-upgrade-15-to-16/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..38a1543d51 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-15-to-16/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: major-upgrade-15-to-16 +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: major-upgrade-15-to-16 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 diff --git a/e2e-tests/tests/major-upgrade-16-to-17/00-assert.yaml b/e2e-tests/tests/major-upgrade-16-to-17/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/major-upgrade-16-to-17/00-deploy-operator.yaml b/e2e-tests/tests/major-upgrade-16-to-17/00-deploy-operator.yaml new file mode 100644 index 0000000000..7faf4da852 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/00-deploy-operator.yaml @@ -0,0 +1,14 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client + deploy_s3_secrets diff --git a/e2e-tests/tests/major-upgrade-16-to-17/01-assert.yaml b/e2e-tests/tests/major-upgrade-16-to-17/01-assert.yaml new file mode 100644 index 0000000000..68768f52cd --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/01-assert.yaml @@ -0,0 +1,135 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: major-upgrade-16-to-17-repo-host + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-16-to-17 + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-16-to-17 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-16-to-17 + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-16-to-17 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: major-upgrade-16-to-17-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-16-to-17 + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-16-to-17 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-16-to-17 + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: major-upgrade-16-to-17 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: major-upgrade-16-to-17 + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: major-upgrade-16-to-17 +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/major-upgrade-16-to-17/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade-16-to-17/01-create-cluster.yaml new file mode 100644 index 0000000000..536619c3ac --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/01-create-cluster.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr \ + | yq eval ' + .spec.postgresVersion = 16 | + .spec.image = "perconalab/percona-postgresql-operator:main-ppg16-postgres" | + .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | + .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-pgbouncer16" | + .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-pgbackrest16" | + .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | + .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.6"}]' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade-16-to-17/02-write-data.yaml b/e2e-tests/tests/major-upgrade-16-to-17/02-write-data.yaml new file mode 100644 index 0000000000..4a47ba1218 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/02-write-data.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'CREATE DATABASE myapp; \c myapp \\\ CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY);' \ + "postgres:$(get_psql_user_pass major-upgrade-16-to-17-pguser-postgres)@$(get_psql_user_host major-upgrade-16-to-17-pguser-postgres)" + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ + "postgres:$(get_psql_user_pass major-upgrade-16-to-17-pguser-postgres)@$(get_psql_user_host major-upgrade-16-to-17-pguser-postgres)" + + run_psql_local \ + '\c postgres \\\ CREATE EXTENSION pg_cron' \ + "postgres:$(get_psql_user_pass major-upgrade-16-to-17-pguser-postgres)@$(get_psql_user_host major-upgrade-16-to-17-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade-16-to-17/03-assert.yaml b/e2e-tests/tests/major-upgrade-16-to-17/03-assert.yaml new file mode 100644 index 0000000000..6848a5b79a --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/03-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 03-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade-16-to-17/03-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-16-to-17/03-read-from-primary.yaml new file mode 100644 index 0000000000..7d46c9700c --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/03-read-from-primary.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-16-to-17-pguser-postgres)@$(get_psql_user_host major-upgrade-16-to-17-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 03-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/16-assert.yaml b/e2e-tests/tests/major-upgrade-16-to-17/04-assert.yaml similarity index 82% rename from e2e-tests/tests/major-upgrade/16-assert.yaml rename to e2e-tests/tests/major-upgrade-16-to-17/04-assert.yaml index e52b25e2cb..7d29d8d3f4 100644 --- a/e2e-tests/tests/major-upgrade/16-assert.yaml +++ b/e2e-tests/tests/major-upgrade-16-to-17/04-assert.yaml @@ -9,7 +9,7 @@ commands: apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: major-upgrade + name: major-upgrade-16-to-17 spec: postgresVersion: 17 status: @@ -29,10 +29,10 @@ kind: Job apiVersion: batch/v1 metadata: labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-16-to-17 postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/16-16-to-17.yaml b/e2e-tests/tests/major-upgrade-16-to-17/04-upgrade.yaml similarity index 92% rename from e2e-tests/tests/major-upgrade/16-16-to-17.yaml rename to e2e-tests/tests/major-upgrade-16-to-17/04-upgrade.yaml index 5f7bfc6e66..0371bb9801 100644 --- a/e2e-tests/tests/major-upgrade/16-16-to-17.yaml +++ b/e2e-tests/tests/major-upgrade-16-to-17/04-upgrade.yaml @@ -13,7 +13,7 @@ commands: metadata: name: 16-to-17 spec: - postgresClusterName: major-upgrade + postgresClusterName: major-upgrade-16-to-17 image: ${IMAGE_UPGRADE} fromPostgresVersion: 16 toPostgresVersion: 17 @@ -21,4 +21,3 @@ commands: toPgBouncerImage: $(get_container_image "pgbouncer" 17) toPgBackRestImage: $(get_container_image "pgbackrest" 17) EOF - diff --git a/e2e-tests/tests/major-upgrade/17-assert.yaml b/e2e-tests/tests/major-upgrade-16-to-17/05-assert.yaml similarity index 77% rename from e2e-tests/tests/major-upgrade/17-assert.yaml rename to e2e-tests/tests/major-upgrade-16-to-17/05-assert.yaml index 6af985e4b7..b274dbb3e1 100644 --- a/e2e-tests/tests/major-upgrade/17-assert.yaml +++ b/e2e-tests/tests/major-upgrade-16-to-17/05-assert.yaml @@ -3,7 +3,7 @@ kind: TestAssert timeout: 660 commands: - script: |- - kubectl get postgrescluster major-upgrade \ + kubectl get postgrescluster major-upgrade-16-to-17 \ -n ${NAMESPACE} \ -o yaml \ | yq eval '.status.pgbackrest.repos' - @@ -11,11 +11,11 @@ commands: apiVersion: postgres-operator.crunchydata.com/v1beta1 kind: PostgresCluster metadata: - name: major-upgrade + name: major-upgrade-16-to-17 status: pgbackrest: repos: - bound: true - name: repo4 + name: repo2 replicaCreateBackupComplete: true stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade-16-to-17/05-change-repo.yaml b/e2e-tests/tests/major-upgrade-16-to-17/05-change-repo.yaml new file mode 100644 index 0000000000..93c1ed2c8a --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/05-change-repo.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + kubectl patch \ + -n $NAMESPACE \ + perconapgcluster major-upgrade-16-to-17 \ + --type='json' \ + -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo2"}]' diff --git a/e2e-tests/tests/major-upgrade/18-assert.yaml b/e2e-tests/tests/major-upgrade-16-to-17/06-assert.yaml similarity index 83% rename from e2e-tests/tests/major-upgrade/18-assert.yaml rename to e2e-tests/tests/major-upgrade-16-to-17/06-assert.yaml index 0bc5ed7dcc..1d2a60a91e 100644 --- a/e2e-tests/tests/major-upgrade/18-assert.yaml +++ b/e2e-tests/tests/major-upgrade-16-to-17/06-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-16-to-17 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo2 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -23,8 +23,8 @@ kind: PerconaPGBackup metadata: name: backup-after-16-to-17 spec: - pgCluster: major-upgrade - repoName: repo4 + pgCluster: major-upgrade-16-to-17 + repoName: repo2 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/18-run-backup.yaml b/e2e-tests/tests/major-upgrade-16-to-17/06-run-backup.yaml similarity index 70% rename from e2e-tests/tests/major-upgrade/18-run-backup.yaml rename to e2e-tests/tests/major-upgrade-16-to-17/06-run-backup.yaml index 9a378656f4..2378d23ca8 100644 --- a/e2e-tests/tests/major-upgrade/18-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade-16-to-17/06-run-backup.yaml @@ -3,7 +3,7 @@ kind: PerconaPGBackup metadata: name: backup-after-16-to-17 spec: - pgCluster: major-upgrade - repoName: repo4 + pgCluster: major-upgrade-16-to-17 + repoName: repo2 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade-16-to-17/07-assert.yaml b/e2e-tests/tests/major-upgrade-16-to-17/07-assert.yaml new file mode 100644 index 0000000000..c86dbb55fc --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/07-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 07-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade-16-to-17/07-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-16-to-17/07-read-from-primary.yaml new file mode 100644 index 0000000000..cc8eda472b --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/07-read-from-primary.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-16-to-17-pguser-postgres)@$(get_psql_user_host major-upgrade-16-to-17-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 07-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade-16-to-17/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/major-upgrade-16-to-17/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..1a5cdbe2b0 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-16-to-17/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: major-upgrade-16-to-17 +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: major-upgrade-16-to-17 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 diff --git a/e2e-tests/tests/major-upgrade-17-to-18/00-assert.yaml b/e2e-tests/tests/major-upgrade-17-to-18/00-assert.yaml new file mode 100644 index 0000000000..ae5a062d84 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/00-assert.yaml @@ -0,0 +1,24 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: perconapgclusters.pgv2.percona.com +spec: + group: pgv2.percona.com + names: + kind: PerconaPGCluster + listKind: PerconaPGClusterList + plural: perconapgclusters + singular: perconapgcluster + scope: Namespaced +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: check-operator-deploy-status +timeout: 120 +commands: + - script: kubectl assert exist-enhanced deployment percona-postgresql-operator -n ${OPERATOR_NS:-$NAMESPACE} --field-selector status.readyReplicas=1 diff --git a/e2e-tests/tests/major-upgrade-17-to-18/00-deploy-operator.yaml b/e2e-tests/tests/major-upgrade-17-to-18/00-deploy-operator.yaml new file mode 100644 index 0000000000..7faf4da852 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/00-deploy-operator.yaml @@ -0,0 +1,14 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + init_temp_dir # do this only in the first TestStep + + deploy_operator + deploy_client + deploy_s3_secrets diff --git a/e2e-tests/tests/major-upgrade-17-to-18/01-assert.yaml b/e2e-tests/tests/major-upgrade-17-to-18/01-assert.yaml new file mode 100644 index 0000000000..e209fb7998 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/01-assert.yaml @@ -0,0 +1,135 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 120 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + name: major-upgrade-17-to-18-repo-host + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-17-to-18 + postgres-operator.crunchydata.com/data: pgbackrest + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-dedicated: '' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-17-to-18 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: StatefulSet +apiVersion: apps/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-17-to-18 + postgres-operator.crunchydata.com/data: postgres + postgres-operator.crunchydata.com/instance-set: instance1 + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-17-to-18 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 1 + readyReplicas: 1 + currentReplicas: 1 + updatedReplicas: 1 + collisionCount: 0 +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: major-upgrade-17-to-18-pgbouncer + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-17-to-18 + postgres-operator.crunchydata.com/role: pgbouncer + annotations: + deployment.kubernetes.io/revision: '1' + ownerReferences: + - apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + name: major-upgrade-17-to-18 + controller: true + blockOwnerDeletion: true +status: + observedGeneration: 1 + replicas: 3 + updatedReplicas: 3 + readyReplicas: 3 +--- +kind: Job +apiVersion: batch/v1 +metadata: + labels: + postgres-operator.crunchydata.com/cluster: major-upgrade-17-to-18 + postgres-operator.crunchydata.com/pgbackrest: '' + postgres-operator.crunchydata.com/pgbackrest-backup: replica-create + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGBackup + controller: true + blockOwnerDeletion: true +status: + succeeded: 1 +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: major-upgrade-17-to-18 + ownerReferences: + - apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + name: major-upgrade-17-to-18 + controller: true + blockOwnerDeletion: true + finalizers: + - postgres-operator.crunchydata.com/finalizer +status: + instances: + - name: instance1 + readyReplicas: 3 + replicas: 3 + updatedReplicas: 3 + observedGeneration: 1 + pgbackrest: + repoHost: + apiVersion: apps/v1 + kind: StatefulSet + ready: true + repos: + - bound: true + name: repo1 + replicaCreateBackupComplete: true + stanzaCreated: true + proxy: + pgBouncer: + readyReplicas: 3 + replicas: 3 +--- +apiVersion: pgv2.percona.com/v2 +kind: PerconaPGCluster +metadata: + name: major-upgrade-17-to-18 +status: + pgbouncer: + ready: 3 + size: 3 + postgres: + instances: + - name: instance1 + ready: 3 + size: 3 + ready: 3 + size: 3 + state: ready diff --git a/e2e-tests/tests/major-upgrade-17-to-18/01-create-cluster.yaml b/e2e-tests/tests/major-upgrade-17-to-18/01-create-cluster.yaml new file mode 100644 index 0000000000..d446b8d35c --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/01-create-cluster.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 10 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + get_cr \ + | yq eval ' + .spec.postgresVersion = 17 | + .spec.image = "perconalab/percona-postgresql-operator:main-ppg17-postgres" | + .spec.instances[0].dataVolumeClaimSpec.resources.requests.storage = "3Gi" | + .spec.proxy.pgBouncer.image = "perconalab/percona-postgresql-operator:main-pgbouncer17" | + .spec.backups.pgbackrest.image = "perconalab/percona-postgresql-operator:main-pgbackrest17" | + .spec.patroni.dynamicConfiguration.postgresql.parameters.shared_preload_libraries = "pg_cron" | + .spec.extensions.custom += [{"name": "pg_cron", "version": "1.6.6"}]' \ + | kubectl -n "${NAMESPACE}" apply -f - diff --git a/e2e-tests/tests/major-upgrade-17-to-18/02-write-data.yaml b/e2e-tests/tests/major-upgrade-17-to-18/02-write-data.yaml new file mode 100644 index 0000000000..f2961b017f --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/02-write-data.yaml @@ -0,0 +1,20 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + run_psql_local \ + 'CREATE DATABASE myapp; \c myapp \\\ CREATE TABLE IF NOT EXISTS myApp (id int PRIMARY KEY);' \ + "postgres:$(get_psql_user_pass major-upgrade-17-to-18-pguser-postgres)@$(get_psql_user_host major-upgrade-17-to-18-pguser-postgres)" + + run_psql_local \ + '\c myapp \\\ INSERT INTO myApp (id) VALUES (100500)' \ + "postgres:$(get_psql_user_pass major-upgrade-17-to-18-pguser-postgres)@$(get_psql_user_host major-upgrade-17-to-18-pguser-postgres)" + + run_psql_local \ + '\c postgres \\\ CREATE EXTENSION pg_cron' \ + "postgres:$(get_psql_user_pass major-upgrade-17-to-18-pguser-postgres)@$(get_psql_user_host major-upgrade-17-to-18-pguser-postgres)" diff --git a/e2e-tests/tests/major-upgrade-17-to-18/03-assert.yaml b/e2e-tests/tests/major-upgrade-17-to-18/03-assert.yaml new file mode 100644 index 0000000000..6848a5b79a --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/03-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 03-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade-17-to-18/03-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-17-to-18/03-read-from-primary.yaml new file mode 100644 index 0000000000..65c282dc79 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/03-read-from-primary.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-17-to-18-pguser-postgres)@$(get_psql_user_host major-upgrade-17-to-18-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 03-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade/20-assert.yaml b/e2e-tests/tests/major-upgrade-17-to-18/04-assert.yaml similarity index 82% rename from e2e-tests/tests/major-upgrade/20-assert.yaml rename to e2e-tests/tests/major-upgrade-17-to-18/04-assert.yaml index ed27544cb4..e843705f78 100644 --- a/e2e-tests/tests/major-upgrade/20-assert.yaml +++ b/e2e-tests/tests/major-upgrade-17-to-18/04-assert.yaml @@ -9,7 +9,7 @@ commands: apiVersion: pgv2.percona.com/v2 kind: PerconaPGCluster metadata: - name: major-upgrade + name: major-upgrade-17-to-18 spec: postgresVersion: 18 status: @@ -29,10 +29,10 @@ kind: Job apiVersion: batch/v1 metadata: labels: - postgres-operator.crunchydata.com/cluster: major-upgrade + postgres-operator.crunchydata.com/cluster: major-upgrade-17-to-18 postgres-operator.crunchydata.com/pgbackrest: '' postgres-operator.crunchydata.com/pgbackrest-backup: replica-create - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo1 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup diff --git a/e2e-tests/tests/major-upgrade/20-17-to-18.yaml b/e2e-tests/tests/major-upgrade-17-to-18/04-upgrade.yaml similarity index 92% rename from e2e-tests/tests/major-upgrade/20-17-to-18.yaml rename to e2e-tests/tests/major-upgrade-17-to-18/04-upgrade.yaml index 7c60208223..a81b47ca25 100644 --- a/e2e-tests/tests/major-upgrade/20-17-to-18.yaml +++ b/e2e-tests/tests/major-upgrade-17-to-18/04-upgrade.yaml @@ -13,7 +13,7 @@ commands: metadata: name: 17-to-18 spec: - postgresClusterName: major-upgrade + postgresClusterName: major-upgrade-17-to-18 image: ${IMAGE_UPGRADE} fromPostgresVersion: 17 toPostgresVersion: 18 @@ -21,4 +21,3 @@ commands: toPgBouncerImage: $(get_container_image "pgbouncer" 18) toPgBackRestImage: $(get_container_image "pgbackrest" 18) EOF - diff --git a/e2e-tests/tests/major-upgrade-17-to-18/05-assert.yaml b/e2e-tests/tests/major-upgrade-17-to-18/05-assert.yaml new file mode 100644 index 0000000000..1b7f090e62 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/05-assert.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 660 +commands: +- script: |- + kubectl get postgrescluster major-upgrade-17-to-18 \ + -n ${NAMESPACE} \ + -o yaml \ + | yq eval '.status.pgbackrest.repos' - +--- +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: major-upgrade-17-to-18 +status: + pgbackrest: + repos: + - bound: true + name: repo2 + replicaCreateBackupComplete: true + stanzaCreated: true diff --git a/e2e-tests/tests/major-upgrade-17-to-18/05-change-repo.yaml b/e2e-tests/tests/major-upgrade-17-to-18/05-change-repo.yaml new file mode 100644 index 0000000000..4b0ddb6c37 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/05-change-repo.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: |- + set -o errexit + set -o xtrace + + kubectl patch \ + -n $NAMESPACE \ + perconapgcluster major-upgrade-17-to-18 \ + --type='json' \ + -p='[{"op": "replace", "path": "/spec/backups/pgbackrest/repos/0/name", "value": "repo2"}]' diff --git a/e2e-tests/tests/major-upgrade/22-assert.yaml b/e2e-tests/tests/major-upgrade-17-to-18/06-assert.yaml similarity index 83% rename from e2e-tests/tests/major-upgrade/22-assert.yaml rename to e2e-tests/tests/major-upgrade-17-to-18/06-assert.yaml index 38642a86fb..579b9f70f2 100644 --- a/e2e-tests/tests/major-upgrade/22-assert.yaml +++ b/e2e-tests/tests/major-upgrade-17-to-18/06-assert.yaml @@ -9,7 +9,7 @@ metadata: postgres-operator.crunchydata.com/pgbackrest-backup: backup-after-17-to-18 labels: postgres-operator.crunchydata.com/pgbackrest-backup: manual - postgres-operator.crunchydata.com/pgbackrest-repo: repo4 + postgres-operator.crunchydata.com/pgbackrest-repo: repo2 ownerReferences: - apiVersion: pgv2.percona.com/v2 kind: PerconaPGBackup @@ -23,8 +23,8 @@ kind: PerconaPGBackup metadata: name: backup-after-17-to-18 spec: - pgCluster: major-upgrade - repoName: repo4 + pgCluster: major-upgrade-17-to-18 + repoName: repo2 options: - --type=full status: diff --git a/e2e-tests/tests/major-upgrade/22-run-backup.yaml b/e2e-tests/tests/major-upgrade-17-to-18/06-run-backup.yaml similarity index 70% rename from e2e-tests/tests/major-upgrade/22-run-backup.yaml rename to e2e-tests/tests/major-upgrade-17-to-18/06-run-backup.yaml index 105493b19c..9804bfd24f 100644 --- a/e2e-tests/tests/major-upgrade/22-run-backup.yaml +++ b/e2e-tests/tests/major-upgrade-17-to-18/06-run-backup.yaml @@ -3,7 +3,7 @@ kind: PerconaPGBackup metadata: name: backup-after-17-to-18 spec: - pgCluster: major-upgrade - repoName: repo4 + pgCluster: major-upgrade-17-to-18 + repoName: repo2 options: - --type=full diff --git a/e2e-tests/tests/major-upgrade-17-to-18/07-assert.yaml b/e2e-tests/tests/major-upgrade-17-to-18/07-assert.yaml new file mode 100644 index 0000000000..c86dbb55fc --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/07-assert.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 30 +--- +kind: ConfigMap +apiVersion: v1 +metadata: + name: 07-read-from-primary +data: + data: ' 100500' diff --git a/e2e-tests/tests/major-upgrade-17-to-18/07-read-from-primary.yaml b/e2e-tests/tests/major-upgrade-17-to-18/07-read-from-primary.yaml new file mode 100644 index 0000000000..8656f7a5ca --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/07-read-from-primary.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 30 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-17-to-18-pguser-postgres)@$(get_psql_user_host major-upgrade-17-to-18-pguser-postgres)") + + kubectl create configmap -n "${NAMESPACE}" 07-read-from-primary --from-literal=data="${data}" diff --git a/e2e-tests/tests/major-upgrade-17-to-18/99-remove-cluster-gracefully.yaml b/e2e-tests/tests/major-upgrade-17-to-18/99-remove-cluster-gracefully.yaml new file mode 100644 index 0000000000..5568a3da31 --- /dev/null +++ b/e2e-tests/tests/major-upgrade-17-to-18/99-remove-cluster-gracefully.yaml @@ -0,0 +1,21 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: pgv2.percona.com/v2 + kind: PerconaPGCluster + metadata: + name: major-upgrade-17-to-18 +- apiVersion: postgres-operator.crunchydata.com/v1beta1 + kind: PostgresCluster + metadata: + name: major-upgrade-17-to-18 +commands: + - script: |- + set -o errexit + set -o xtrace + + source ../../functions + + remove_all_finalizers + destroy_operator + timeout: 60 diff --git a/e2e-tests/tests/major-upgrade/11-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/11-read-from-primary.yaml deleted file mode 100644 index 7ecb6090a2..0000000000 --- a/e2e-tests/tests/major-upgrade/11-read-from-primary.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -timeout: 30 -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - - kubectl create configmap -n "${NAMESPACE}" 11-read-from-primary --from-literal=data="${data}" \ No newline at end of file diff --git a/e2e-tests/tests/major-upgrade/15-read-from-primary.yaml b/e2e-tests/tests/major-upgrade/15-read-from-primary.yaml deleted file mode 100644 index 23a10ac997..0000000000 --- a/e2e-tests/tests/major-upgrade/15-read-from-primary.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -timeout: 30 -commands: - - script: |- - set -o errexit - set -o xtrace - - source ../../functions - data=$(run_psql_local '\c myapp \\\ SELECT * from myApp;' "postgres:$(get_psql_user_pass major-upgrade-pguser-postgres)@$(get_psql_user_host major-upgrade-pguser-postgres)") - - kubectl create configmap -n "${NAMESPACE}" 15-read-from-primary --from-literal=data="${data}" \ No newline at end of file diff --git a/e2e-tests/tests/major-upgrade/21-assert.yaml b/e2e-tests/tests/major-upgrade/21-assert.yaml deleted file mode 100644 index 6af985e4b7..0000000000 --- a/e2e-tests/tests/major-upgrade/21-assert.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -timeout: 660 -commands: -- script: |- - kubectl get postgrescluster major-upgrade \ - -n ${NAMESPACE} \ - -o yaml \ - | yq eval '.status.pgbackrest.repos' - ---- -apiVersion: postgres-operator.crunchydata.com/v1beta1 -kind: PostgresCluster -metadata: - name: major-upgrade -status: - pgbackrest: - repos: - - bound: true - name: repo4 - replicaCreateBackupComplete: true - stanzaCreated: true From dc1d761621b365e3f5aec685596c580e3731c98b Mon Sep 17 00:00:00 2001 From: Natalia Marukovich Date: Tue, 17 Feb 2026 14:14:27 +0100 Subject: [PATCH 300/300] add run-release --- e2e-tests/run-release.csv | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/e2e-tests/run-release.csv b/e2e-tests/run-release.csv index 1151e8b91b..cac527dcbb 100644 --- a/e2e-tests/run-release.csv +++ b/e2e-tests/run-release.csv @@ -9,7 +9,11 @@ demand-backup-offline-snapshot finalizers init-deploy huge-pages -major-upgrade +major-upgrade-13-to-14 +major-upgrade-14-to-15 +major-upgrade-15-to-16 +major-upgrade-16-to-17 +major-upgrade-17-to-18 monitoring monitoring-pmm3 one-pod