mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-09-07 15:32:21 +02:00
Compare commits
10 Commits
e786a7faf0
...
275f31f6fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
275f31f6fe | ||
|
|
2cc4e9905d | ||
|
|
39881b0d9c | ||
|
|
1a701f66eb | ||
|
|
21aadbfd11 | ||
|
|
b0e4538147 | ||
|
|
bf955430cb | ||
|
|
3cc6a882c8 | ||
|
|
f4fa18e592 | ||
|
|
26de2dadaf |
@ -1,6 +1,6 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [0.13.1](https://github.com/cloudnative-pg/plugin-barman-cloud/compare/v0.13.0...v0.13.1) (2026-06-26)
|
## [0.13.1](https://github.com/cloudnative-pg/plugin-barman-cloud/compare/v0.13.0...v0.13.1) (2026-07-09)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
@ -12,8 +12,10 @@
|
|||||||
* **deps:** Update all non-major go dependencies to 8d9302e ([#975](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/975)) ([0c687cb](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/0c687cbbf13f4ce5ca1690d4dcf768d76cb4731a))
|
* **deps:** Update all non-major go dependencies to 8d9302e ([#975](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/975)) ([0c687cb](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/0c687cbbf13f4ce5ca1690d4dcf768d76cb4731a))
|
||||||
* **deps:** Update all non-major go dependencies to v2.30.0 ([#957](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/957)) ([61b82ce](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/61b82ce250e95f04d49d0fb427e79364f2d900c0))
|
* **deps:** Update all non-major go dependencies to v2.30.0 ([#957](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/957)) ([61b82ce](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/61b82ce250e95f04d49d0fb427e79364f2d900c0))
|
||||||
* **deps:** Update k8s.io/utils digest to a95e086 ([#968](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/968)) ([f7f0136](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/f7f0136520b1032698b26e33e6eff1caa01173f5))
|
* **deps:** Update k8s.io/utils digest to a95e086 ([#968](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/968)) ([f7f0136](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/f7f0136520b1032698b26e33e6eff1caa01173f5))
|
||||||
|
* **deps:** Update k8s.io/utils digest to be93311 ([#986](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/986)) ([2cc4e99](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/2cc4e9905db6b1d1c5788dd6093a1a7d330d9064))
|
||||||
* **deps:** Update kubernetes monorepo to v0.36.2 ([#958](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/958)) ([030b28c](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/030b28c4b9aee205f7a43f1fcc4da363b50839d9))
|
* **deps:** Update kubernetes monorepo to v0.36.2 ([#958](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/958)) ([030b28c](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/030b28c4b9aee205f7a43f1fcc4da363b50839d9))
|
||||||
* Inject barman sidecar in replica clusters bootstrapped with pg_basebackup ([#965](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/965)) ([eb5e860](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/eb5e8607752d60bf36b4a9ddcaa5bb447f323012))
|
* Inject barman sidecar in replica clusters bootstrapped with pg_basebackup ([#965](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/965)) ([eb5e860](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/eb5e8607752d60bf36b4a9ddcaa5bb447f323012))
|
||||||
|
* Reduce startupProbe periodSeconds without losing failure tolerance ([#992](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/992)) ([bf95543](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/bf955430cb58987bbbe3cd2925ea06700cf85609)), closes [#991](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/991)
|
||||||
* Restore WAL from replica source during designated primary promotion ([#966](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/966)) ([c34b232](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/c34b2329ea39f9a1030d9d1225aa4d0a276255eb))
|
* Restore WAL from replica source during designated primary promotion ([#966](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/966)) ([c34b232](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/c34b2329ea39f9a1030d9d1225aa4d0a276255eb))
|
||||||
|
|
||||||
## [0.13.0](https://github.com/cloudnative-pg/plugin-barman-cloud/compare/v0.12.0...v0.13.0) (2026-06-10)
|
## [0.13.0](https://github.com/cloudnative-pg/plugin-barman-cloud/compare/v0.12.0...v0.13.0) (2026-06-10)
|
||||||
|
|||||||
10
Taskfile.yml
10
Taskfile.yml
@ -46,7 +46,7 @@ tasks:
|
|||||||
- wordlist-ordered
|
- wordlist-ordered
|
||||||
env:
|
env:
|
||||||
# renovate: datasource=git-refs depName=spellcheck lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
# renovate: datasource=git-refs depName=spellcheck lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
||||||
DAGGER_SPELLCHECK_SHA: 679d5056358d3cd838ec226333decff673602937
|
DAGGER_SPELLCHECK_SHA: 7a53f0b7f36c786389a6f72714d5875b9a63e9c1
|
||||||
cmds:
|
cmds:
|
||||||
- >
|
- >
|
||||||
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/spellcheck@${DAGGER_SPELLCHECK_SHA}
|
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/spellcheck@${DAGGER_SPELLCHECK_SHA}
|
||||||
@ -60,7 +60,7 @@ tasks:
|
|||||||
desc: Check for conventional commits
|
desc: Check for conventional commits
|
||||||
env:
|
env:
|
||||||
# renovate: datasource=git-refs depName=commitlint lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
# renovate: datasource=git-refs depName=commitlint lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
||||||
DAGGER_COMMITLINT_SHA: 679d5056358d3cd838ec226333decff673602937
|
DAGGER_COMMITLINT_SHA: 7a53f0b7f36c786389a6f72714d5875b9a63e9c1
|
||||||
cmds:
|
cmds:
|
||||||
- >
|
- >
|
||||||
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/commitlint@${DAGGER_COMMITLINT_SHA}
|
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/commitlint@${DAGGER_COMMITLINT_SHA}
|
||||||
@ -74,7 +74,7 @@ tasks:
|
|||||||
- wordlist-ordered
|
- wordlist-ordered
|
||||||
env:
|
env:
|
||||||
# renovate: datasource=git-refs depName=uncommitted lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
# renovate: datasource=git-refs depName=uncommitted lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
||||||
DAGGER_UNCOMMITTED_SHA: 679d5056358d3cd838ec226333decff673602937
|
DAGGER_UNCOMMITTED_SHA: 7a53f0b7f36c786389a6f72714d5875b9a63e9c1
|
||||||
cmds:
|
cmds:
|
||||||
- GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/uncommitted@${DAGGER_UNCOMMITTED_SHA} check-uncommitted --source . stdout
|
- GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/uncommitted@${DAGGER_UNCOMMITTED_SHA} check-uncommitted --source . stdout
|
||||||
sources:
|
sources:
|
||||||
@ -86,7 +86,7 @@ tasks:
|
|||||||
- controller-gen
|
- controller-gen
|
||||||
env:
|
env:
|
||||||
# renovate: datasource=git-refs depName=crd-gen-refs lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
# renovate: datasource=git-refs depName=crd-gen-refs lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
||||||
DAGGER_CRDGENREF_SHA: 679d5056358d3cd838ec226333decff673602937
|
DAGGER_CRDGENREF_SHA: 7a53f0b7f36c786389a6f72714d5875b9a63e9c1
|
||||||
# renovate: datasource=go depName=github.com/elastic/crd-ref-docs
|
# renovate: datasource=go depName=github.com/elastic/crd-ref-docs
|
||||||
CRDREFDOCS_VERSION: v0.3.0
|
CRDREFDOCS_VERSION: v0.3.0
|
||||||
cmds:
|
cmds:
|
||||||
@ -381,7 +381,7 @@ tasks:
|
|||||||
run: once
|
run: once
|
||||||
env:
|
env:
|
||||||
# renovate: datasource=git-refs depName=controller-gen lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
# renovate: datasource=git-refs depName=controller-gen lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
|
||||||
DAGGER_CONTROLLER_GEN_SHA: 679d5056358d3cd838ec226333decff673602937
|
DAGGER_CONTROLLER_GEN_SHA: 7a53f0b7f36c786389a6f72714d5875b9a63e9c1
|
||||||
cmds:
|
cmds:
|
||||||
- >
|
- >
|
||||||
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/controller-gen@${DAGGER_CONTROLLER_GEN_SHA}
|
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/controller-gen@${DAGGER_CONTROLLER_GEN_SHA}
|
||||||
|
|||||||
@ -22,19 +22,19 @@ barman==3.19.1 \
|
|||||||
--hash=sha256:0a6a9e1babf97687732d8b2a3eb79ea95d55246a5257b9433865cb6e755221c0 \
|
--hash=sha256:0a6a9e1babf97687732d8b2a3eb79ea95d55246a5257b9433865cb6e755221c0 \
|
||||||
--hash=sha256:2f71c4a1f1ba53f694cbdf838bb9906d8ba02b97d1fd3041196e8999bec7a1ee
|
--hash=sha256:2f71c4a1f1ba53f694cbdf838bb9906d8ba02b97d1fd3041196e8999bec7a1ee
|
||||||
# via -r sidecar-requirements.in
|
# via -r sidecar-requirements.in
|
||||||
boto3==1.43.30 \
|
boto3==1.43.36 \
|
||||||
--hash=sha256:6b1ee360f363a457f67a8f5702f522043d8a32d67a97c362ad12075d8b5b531e \
|
--hash=sha256:42942dde254673abcbc9e6e60017c88341a4f49d99d24e1f2e290fb38138c26f \
|
||||||
--hash=sha256:89e982463d94773136ccf69be77cccd54ff1ce351a6aadd1d3437fcb693681b5
|
--hash=sha256:587d7ee92a12e440ad12b0e7f11f3358f0c4d65b19f64726efc94aaf194aff28
|
||||||
# via barman
|
# via barman
|
||||||
botocore==1.43.30 \
|
botocore==1.43.36 \
|
||||||
--hash=sha256:19ed560cb35ae43bf010d37da429a553c07063bf7efea0f2cb53be8a78d3e3d5 \
|
--hash=sha256:3c65fdc39ed01d8dfde1e961b34038aed03c459f8ddf80717a12ac006475e49d \
|
||||||
--hash=sha256:26b1dded84d89b396180916f56900bd2ab1c0d545a66d1d2c3eeb40f772935b2
|
--hash=sha256:4cae47d1b2d426316b85a0087d9e69e048f13bc003b5177d74639fe9dfd28205
|
||||||
# via
|
# via
|
||||||
# boto3
|
# boto3
|
||||||
# s3transfer
|
# s3transfer
|
||||||
certifi==2026.5.20 \
|
certifi==2026.6.17 \
|
||||||
--hash=sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897 \
|
--hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \
|
||||||
--hash=sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d
|
--hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db
|
||||||
# via requests
|
# via requests
|
||||||
cffi==2.0.0 \
|
cffi==2.0.0 \
|
||||||
--hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \
|
--hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \
|
||||||
@ -449,9 +449,9 @@ google-api-core==2.31.0 \
|
|||||||
# via
|
# via
|
||||||
# google-cloud-core
|
# google-cloud-core
|
||||||
# google-cloud-storage
|
# google-cloud-storage
|
||||||
google-auth==2.55.0 \
|
google-auth==2.55.1 \
|
||||||
--hash=sha256:a17cef9dedf98c4ebae2fb0c48c8f75952c877cbc2efe09f329ef16c2783d88a \
|
--hash=sha256:eada68dfd52b3b81191827601e2a0c3fa12540c818534b630ddc5355769c3995 \
|
||||||
--hash=sha256:fcd3a130f575fa36403d38774af1c64a4fbfbca09215f0589d2372b5119697cb
|
--hash=sha256:fb2d9b730f2c9b8d326ec8d7222f21aef2ead15bf0513793d6442485d87af0a1
|
||||||
# via
|
# via
|
||||||
# google-api-core
|
# google-api-core
|
||||||
# google-cloud-core
|
# google-cloud-core
|
||||||
@ -654,9 +654,9 @@ requests==2.34.2 \
|
|||||||
# google-api-core
|
# google-api-core
|
||||||
# google-cloud-storage
|
# google-cloud-storage
|
||||||
# msal
|
# msal
|
||||||
s3transfer==0.18.0 \
|
s3transfer==0.19.0 \
|
||||||
--hash=sha256:239c13b09e65ad0346e1be7348b8a202dcad44ac7ea7c6eb858fc881dce739b6 \
|
--hash=sha256:777cc2415536f1debadb5c2ef7779275d0fc0fe0e042411cdd6caebeb2685262 \
|
||||||
--hash=sha256:3760b8b7ec1315da54048b2d626276732bee4300d054d492d4e1d43e20d4ecbd
|
--hash=sha256:ce436931687addc4c1712d52d40b32f53e88315723f107ffa20ba82b05a0f685
|
||||||
# via boto3
|
# via boto3
|
||||||
six==1.17.0 \
|
six==1.17.0 \
|
||||||
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
|
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -20,7 +20,7 @@ require (
|
|||||||
k8s.io/apiextensions-apiserver v0.36.2
|
k8s.io/apiextensions-apiserver v0.36.2
|
||||||
k8s.io/apimachinery v0.36.2
|
k8s.io/apimachinery v0.36.2
|
||||||
k8s.io/client-go v0.36.2
|
k8s.io/client-go v0.36.2
|
||||||
k8s.io/utils v0.0.0-20260617174310-a95e086a2553
|
k8s.io/utils v0.0.0-20260626114624-be93311217bd
|
||||||
sigs.k8s.io/controller-runtime v0.24.1
|
sigs.k8s.io/controller-runtime v0.24.1
|
||||||
sigs.k8s.io/kustomize/api v0.21.1
|
sigs.k8s.io/kustomize/api v0.21.1
|
||||||
sigs.k8s.io/kustomize/kyaml v0.21.1
|
sigs.k8s.io/kustomize/kyaml v0.21.1
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -326,8 +326,8 @@ k8s.io/kube-openapi v0.0.0-20260502001324-b7f5293f4787 h1:kHv8PETbPIVHfqKBYwTNNS
|
|||||||
k8s.io/kube-openapi v0.0.0-20260502001324-b7f5293f4787/go.mod h1:Cyq7UE0QtGe+Zo+/6XFrxiS4Mq0tLyQEONkFzSkfp9o=
|
k8s.io/kube-openapi v0.0.0-20260502001324-b7f5293f4787/go.mod h1:Cyq7UE0QtGe+Zo+/6XFrxiS4Mq0tLyQEONkFzSkfp9o=
|
||||||
k8s.io/streaming v0.36.2 h1:NSKthPPg9UFSKsRauVJUVGH2Dvn8fhKmY4qrMkw/p98=
|
k8s.io/streaming v0.36.2 h1:NSKthPPg9UFSKsRauVJUVGH2Dvn8fhKmY4qrMkw/p98=
|
||||||
k8s.io/streaming v0.36.2/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
|
k8s.io/streaming v0.36.2/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
|
||||||
k8s.io/utils v0.0.0-20260617174310-a95e086a2553 h1:hmGqDecjc8d7HVzWzRFl0QD9bYuYKbBEG7t8xwnVxfI=
|
k8s.io/utils v0.0.0-20260626114624-be93311217bd h1:Ea7fgQ5we8Y9T0OX5o0dAHzQOBRI07D/dEYRaB9ZZEs=
|
||||||
k8s.io/utils v0.0.0-20260617174310-a95e086a2553/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
k8s.io/utils v0.0.0-20260626114624-be93311217bd/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||||
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
|
sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4=
|
||||||
|
|||||||
@ -403,8 +403,9 @@ func reconcilePodSpec(
|
|||||||
envs = append(envs, config.env...)
|
envs = append(envs, config.env...)
|
||||||
|
|
||||||
baseProbe := &corev1.Probe{
|
baseProbe := &corev1.Probe{
|
||||||
FailureThreshold: 10,
|
PeriodSeconds: 1,
|
||||||
TimeoutSeconds: 10,
|
FailureThreshold: 30,
|
||||||
|
TimeoutSeconds: 5,
|
||||||
ProbeHandler: corev1.ProbeHandler{
|
ProbeHandler: corev1.ProbeHandler{
|
||||||
Exec: &corev1.ExecAction{
|
Exec: &corev1.ExecAction{
|
||||||
Command: []string{"/manager", "healthcheck", "unix"},
|
Command: []string{"/manager", "healthcheck", "unix"},
|
||||||
|
|||||||
@ -12,14 +12,14 @@
|
|||||||
rebaseWhen: 'never',
|
rebaseWhen: 'never',
|
||||||
prConcurrentLimit: 5,
|
prConcurrentLimit: 5,
|
||||||
// Override default ignorePaths to scan test/e2e for emulator image dependencies
|
// Override default ignorePaths to scan test/e2e for emulator image dependencies
|
||||||
// Removed: '**/test/**'
|
// Removed: '**/test/**', '**/tests/**' (this repo's e2e Ginkgo packages live
|
||||||
|
// under test/e2e/internal/tests/**, which the plural pattern was excluding)
|
||||||
ignorePaths: [
|
ignorePaths: [
|
||||||
'**/node_modules/**',
|
'**/node_modules/**',
|
||||||
'**/bower_components/**',
|
'**/bower_components/**',
|
||||||
'**/vendor/**',
|
'**/vendor/**',
|
||||||
'**/examples/**',
|
'**/examples/**',
|
||||||
'**/__tests__/**',
|
'**/__tests__/**',
|
||||||
'**/tests/**',
|
|
||||||
'**/__fixtures__/**',
|
'**/__fixtures__/**',
|
||||||
],
|
],
|
||||||
lockFileMaintenance: {
|
lockFileMaintenance: {
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import (
|
|||||||
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/backup"
|
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/backup"
|
||||||
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/credentialrotation"
|
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/credentialrotation"
|
||||||
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/replicacluster"
|
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/replicacluster"
|
||||||
|
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/walrestore"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|||||||
@ -58,7 +58,7 @@ func WithIgnoreExistingResources(ignore bool) InstallOption {
|
|||||||
// DefaultVersion is the default version of cert-manager to install.
|
// DefaultVersion is the default version of cert-manager to install.
|
||||||
//
|
//
|
||||||
// renovate: datasource=github-releases depName=cert-manager/cert-manager
|
// renovate: datasource=github-releases depName=cert-manager/cert-manager
|
||||||
const DefaultVersion = "v1.20.2"
|
const DefaultVersion = "v1.20.3"
|
||||||
|
|
||||||
// Install installs cert-manager using kubectl.
|
// Install installs cert-manager using kubectl.
|
||||||
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {
|
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {
|
||||||
|
|||||||
24
test/e2e/internal/tests/walrestore/doc.go
Normal file
24
test/e2e/internal/tests/walrestore/doc.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
Copyright © contributors to CloudNativePG, established as
|
||||||
|
CloudNativePG a Series of LF Projects, LLC.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package walrestore contains the end-to-end test for the parallel WAL restore
|
||||||
|
// behaviour of the Barman Cloud Plugin: prefetching upcoming segments into the
|
||||||
|
// spool directory, serving later requests from the spool, and tracking the
|
||||||
|
// end-of-wal-stream sentinel.
|
||||||
|
package walrestore
|
||||||
178
test/e2e/internal/tests/walrestore/fixtures.go
Normal file
178
test/e2e/internal/tests/walrestore/fixtures.go
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
Copyright © contributors to CloudNativePG, established as
|
||||||
|
CloudNativePG a Series of LF Projects, LLC.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package walrestore
|
||||||
|
|
||||||
|
import (
|
||||||
|
cloudnativepgv1 "github.com/cloudnative-pg/api/pkg/api/v1"
|
||||||
|
barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
|
|
||||||
|
pluginBarmanCloudV1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
|
||||||
|
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/objectstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
minioName = "minio"
|
||||||
|
objectStoreName = "source"
|
||||||
|
clusterName = "source"
|
||||||
|
s3ClientName = "s3-client"
|
||||||
|
storageSize = "1Gi"
|
||||||
|
// walMaxParallel is the prefetch parallelism under test: for a regular WAL
|
||||||
|
// request the plugin restores the requested segment and prefetches the next
|
||||||
|
// ones, up to this many segments in total.
|
||||||
|
walMaxParallel = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// newObjectStoreResources returns the minio server Deployment/Service/Secret/PVC.
|
||||||
|
func newObjectStoreResources(namespace string) *objectstore.Resources {
|
||||||
|
return objectstore.NewMinioObjectStoreResources(namespace, minioName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newObjectStore returns a minio-backed ObjectStore configured with the WAL
|
||||||
|
// prefetch parallelism (maxParallel) under test. Archiving with gzip makes the
|
||||||
|
// archived segments carry the ".gz" suffix that forged segments are copied from.
|
||||||
|
func newObjectStore(namespace string) *pluginBarmanCloudV1.ObjectStore {
|
||||||
|
store := objectstore.NewMinioObjectStore(namespace, objectStoreName, minioName)
|
||||||
|
store.Spec.Configuration.Wal = &barmanapi.WalBackupConfiguration{
|
||||||
|
MaxParallel: walMaxParallel,
|
||||||
|
Compression: barmanapi.CompressionTypeGzip,
|
||||||
|
}
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
|
// newCluster returns a 2-instance cluster that uses the plugin as its WAL
|
||||||
|
// archiver, so the standby drives WAL restore (and its prefetch/spool/
|
||||||
|
// end-of-wal-stream state machine) through the plugin.
|
||||||
|
func newCluster(namespace string) *cloudnativepgv1.Cluster {
|
||||||
|
return &cloudnativepgv1.Cluster{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "Cluster",
|
||||||
|
APIVersion: "postgresql.cnpg.io/v1",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: clusterName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
Spec: cloudnativepgv1.ClusterSpec{
|
||||||
|
Instances: 2,
|
||||||
|
ImagePullPolicy: corev1.PullAlways,
|
||||||
|
Plugins: []cloudnativepgv1.PluginConfiguration{
|
||||||
|
{
|
||||||
|
Name: "barman-cloud.cloudnative-pg.io",
|
||||||
|
Parameters: map[string]string{
|
||||||
|
"barmanObjectName": objectStoreName,
|
||||||
|
},
|
||||||
|
IsWALArchiver: ptr.To(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PostgresConfiguration: cloudnativepgv1.PostgresConfiguration{
|
||||||
|
Parameters: map[string]string{
|
||||||
|
"log_min_messages": "DEBUG4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
StorageConfiguration: cloudnativepgv1.StorageConfiguration{
|
||||||
|
Size: storageSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newS3ClientDeployment returns a deployment running the AWS CLI configured to
|
||||||
|
// talk to the in-namespace minio service. The test execs `aws s3` commands in
|
||||||
|
// it to forge WAL segments on the object store and to check their presence.
|
||||||
|
func newS3ClientDeployment(namespace string) *appsv1.Deployment {
|
||||||
|
labels := map[string]string{"app": s3ClientName}
|
||||||
|
return &appsv1.Deployment{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "Deployment",
|
||||||
|
APIVersion: "apps/v1",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: s3ClientName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
Spec: appsv1.DeploymentSpec{
|
||||||
|
Replicas: ptr.To(int32(1)),
|
||||||
|
Selector: &metav1.LabelSelector{MatchLabels: labels},
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Labels: labels},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: s3ClientName,
|
||||||
|
// renovate: datasource=docker depName=amazon/aws-cli versioning=docker
|
||||||
|
// Version: 2.35.11
|
||||||
|
Image: "docker.io/amazon/aws-cli@sha256:749bfaf91d690b9a1768083822d620f96c19defdf9ca2dc227eb3695281fda5b",
|
||||||
|
Command: []string{"sleep", "infinity"},
|
||||||
|
Env: []corev1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "AWS_ENDPOINT_URL",
|
||||||
|
Value: "http://" + minioName + ":9000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "AWS_ACCESS_KEY_ID",
|
||||||
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
|
SecretKeyRef: &corev1.SecretKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{Name: minioName},
|
||||||
|
Key: "ACCESS_KEY_ID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "AWS_SECRET_ACCESS_KEY",
|
||||||
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
|
SecretKeyRef: &corev1.SecretKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{Name: minioName},
|
||||||
|
Key: "ACCESS_SECRET_KEY",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "AWS_DEFAULT_REGION",
|
||||||
|
Value: "us-east-1",
|
||||||
|
},
|
||||||
|
// The CRC-based default checksums introduced in AWS
|
||||||
|
// CLI 2.23 are not supported by every S3-compatible
|
||||||
|
// object store, minio included.
|
||||||
|
{
|
||||||
|
Name: "AWS_REQUEST_CHECKSUM_CALCULATION",
|
||||||
|
Value: "when_required",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "AWS_RESPONSE_CHECKSUM_VALIDATION",
|
||||||
|
Value: "when_required",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SecurityContext: &corev1.SecurityContext{
|
||||||
|
AllowPrivilegeEscalation: ptr.To(false),
|
||||||
|
SeccompProfile: &corev1.SeccompProfile{
|
||||||
|
Type: corev1.SeccompProfileTypeRuntimeDefault,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
312
test/e2e/internal/tests/walrestore/walrestore.go
Normal file
312
test/e2e/internal/tests/walrestore/walrestore.go
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
Copyright © contributors to CloudNativePG, established as
|
||||||
|
CloudNativePG a Series of LF Projects, LLC.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package walrestore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
apitypes "k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
executil "k8s.io/client-go/util/exec"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
|
internalClient "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/client"
|
||||||
|
internalCluster "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/cluster"
|
||||||
|
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/command"
|
||||||
|
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/deployment"
|
||||||
|
nmsp "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/namespace"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// spoolDirectory is where the plugin sidecar prefetches WAL segments and
|
||||||
|
// records the end-of-wal-stream sentinel. It must match the SPOOL_DIRECTORY
|
||||||
|
// the operator injects on the sidecar (internal/cnpgi/operator/lifecycle.go),
|
||||||
|
// which lives on the CloudNativePG scratch-data volume shared with the
|
||||||
|
// postgres container, so the path is visible from the postgres container too.
|
||||||
|
spoolDirectory = "/controller/wal-restore-spool"
|
||||||
|
// pgWalPath is PgDataPath + "/pg_wal" in the CloudNativePG operand image.
|
||||||
|
pgWalPath = "/var/lib/postgresql/data/pgdata/pg_wal"
|
||||||
|
// endOfWALStreamFlag is the sentinel file the barman-cloud restorer writes in
|
||||||
|
// the spool to record that the archive ran out of segments.
|
||||||
|
endOfWALStreamFlag = "end-of-wal-stream"
|
||||||
|
// managerExecutable is the CloudNativePG instance manager. Its wal-restore
|
||||||
|
// subcommand delegates to the plugin when the cluster uses it as WAL archiver.
|
||||||
|
managerExecutable = "/controller/manager"
|
||||||
|
// postgresContainer is the container we exec into on instance pods.
|
||||||
|
postgresContainer = "postgres"
|
||||||
|
// walLogDir is the WALs subdirectory (timeline + log id) the forged segments
|
||||||
|
// live under; a freshly bootstrapped, idle cluster stays within it.
|
||||||
|
walLogDir = "0000000100000000"
|
||||||
|
// bucket is the destination bucket of the minio ObjectStore.
|
||||||
|
bucket = "backups"
|
||||||
|
)
|
||||||
|
|
||||||
|
// walFile returns the name of the n-th forged WAL segment (segment 0xF0+n on
|
||||||
|
// timeline 1, log 0, for n <= 15). The high segment number keeps it out of the
|
||||||
|
// range an idle PostgreSQL would archive on its own.
|
||||||
|
func walFile(n int) string {
|
||||||
|
return fmt.Sprintf("0000000100000000%08X", 0xF0+n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// walObjectURI returns the s3 URI of a wals object (by file name) in the store.
|
||||||
|
func walObjectURI(name string) string {
|
||||||
|
return fmt.Sprintf("s3://%s/%s/wals/%s/%s", bucket, clusterName, walLogDir, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// execInPod runs a command in the given container and returns stdout, stderr
|
||||||
|
// and the error (non-nil for a non-zero exit code).
|
||||||
|
func execInPod(
|
||||||
|
ctx context.Context,
|
||||||
|
clientSet *kubernetes.Clientset,
|
||||||
|
cfg *rest.Config,
|
||||||
|
namespace, pod, container string,
|
||||||
|
args ...string,
|
||||||
|
) (string, string, error) {
|
||||||
|
return command.ExecuteInContainer(
|
||||||
|
ctx,
|
||||||
|
*clientSet,
|
||||||
|
cfg,
|
||||||
|
command.ContainerLocator{
|
||||||
|
NamespaceName: namespace,
|
||||||
|
PodName: pod,
|
||||||
|
ContainerName: container,
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
args,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test drives the plugin's parallel WAL restore directly: it invokes the
|
||||||
|
// instance-manager wal-restore command on the standby (which delegates to the
|
||||||
|
// plugin) and asserts the prefetch/spool/end-of-wal-stream state machine with
|
||||||
|
// maxParallel = 3. To control the archive deterministically, it forges WAL
|
||||||
|
// segments on the object store by copying a real archived segment under new
|
||||||
|
// names.
|
||||||
|
var _ = Describe("Parallel WAL restore", func() {
|
||||||
|
var (
|
||||||
|
namespace *corev1.Namespace
|
||||||
|
cl client.Client
|
||||||
|
clientSet *kubernetes.Clientset
|
||||||
|
cfg *rest.Config
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func(ctx SpecContext) {
|
||||||
|
var err error
|
||||||
|
cl, _, err = internalClient.NewClient()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
clientSet, cfg, err = internalClient.NewClientSet()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
namespace, err = nmsp.CreateUniqueNamespace(ctx, cl, "wal-restore-parallel")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func(ctx SpecContext) {
|
||||||
|
Expect(cl.Delete(ctx, namespace)).To(Succeed())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("prefetches segments, serves them from the spool and tracks end-of-wal-stream",
|
||||||
|
func(ctx SpecContext) {
|
||||||
|
ns := namespace.Name
|
||||||
|
|
||||||
|
By("creating the object store backing resources")
|
||||||
|
Expect(newObjectStoreResources(ns).Create(ctx, cl)).To(Succeed())
|
||||||
|
|
||||||
|
By("creating the ObjectStore with WAL maxParallel")
|
||||||
|
Expect(cl.Create(ctx, newObjectStore(ns))).To(Succeed())
|
||||||
|
|
||||||
|
By("deploying the S3 client used to forge and inspect WAL segments")
|
||||||
|
Expect(cl.Create(ctx, newS3ClientDeployment(ns))).To(Succeed())
|
||||||
|
|
||||||
|
By("creating the cluster using the plugin as WAL archiver")
|
||||||
|
cluster := newCluster(ns)
|
||||||
|
Expect(cl.Create(ctx, cluster)).To(Succeed())
|
||||||
|
|
||||||
|
By("waiting for the cluster to become ready")
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(cl.Get(ctx,
|
||||||
|
apitypes.NamespacedName{Name: clusterName, Namespace: ns},
|
||||||
|
cluster)).To(Succeed())
|
||||||
|
g.Expect(internalCluster.IsReady(*cluster)).To(BeTrue())
|
||||||
|
}).WithTimeout(10 * time.Minute).WithPolling(10 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
By("waiting for the S3 client to become ready")
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
ready, err := deployment.IsReady(ctx, cl,
|
||||||
|
apitypes.NamespacedName{Name: s3ClientName, Namespace: ns})
|
||||||
|
g.Expect(err).NotTo(HaveOccurred())
|
||||||
|
g.Expect(ready).To(BeTrue())
|
||||||
|
}).WithTimeout(2 * time.Minute).WithPolling(5 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
primary := cluster.Status.CurrentPrimary
|
||||||
|
Expect(primary).NotTo(BeEmpty())
|
||||||
|
standby := clusterName + "-2"
|
||||||
|
|
||||||
|
var s3ClientPods corev1.PodList
|
||||||
|
Expect(cl.List(ctx, &s3ClientPods,
|
||||||
|
client.InNamespace(ns),
|
||||||
|
client.MatchingLabels{"app": s3ClientName})).To(Succeed())
|
||||||
|
Expect(s3ClientPods.Items).NotTo(BeEmpty())
|
||||||
|
s3Client := s3ClientPods.Items[0].Name
|
||||||
|
|
||||||
|
// Operations scoped to the fixed pods/clients, kept as closures so the
|
||||||
|
// step assertions below read like the original state-machine table.
|
||||||
|
restore := func(name string) error {
|
||||||
|
_, _, err := execInPod(ctx, clientSet, cfg, ns, standby, postgresContainer,
|
||||||
|
managerExecutable, "wal-restore", name, pgWalPath+"/"+name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
existsIn := func(dir, name string) bool {
|
||||||
|
_, _, err := execInPod(ctx, clientSet, cfg, ns, standby, postgresContainer,
|
||||||
|
"test", "-f", dir+"/"+name)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
flagSet := func() bool { return existsIn(spoolDirectory, endOfWALStreamFlag) }
|
||||||
|
spoolSegments := func() int {
|
||||||
|
out, _, _ := execInPod(ctx, clientSet, cfg, ns, standby, postgresContainer,
|
||||||
|
"sh", "-c",
|
||||||
|
"ls -1 "+spoolDirectory+" 2>/dev/null | grep -Ec '^[0-9A-F]{24}$' || true")
|
||||||
|
n, _ := strconv.Atoi(strings.TrimSpace(out))
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
purgeSpool := func() {
|
||||||
|
_, _, _ = execInPod(ctx, clientSet, cfg, ns, standby, postgresContainer,
|
||||||
|
"sh", "-c", "rm -f "+spoolDirectory+"/* 2>/dev/null; true")
|
||||||
|
}
|
||||||
|
forge := func(src, dst string) {
|
||||||
|
// ExecuteInContainer drops stdout/stderr on a non-zero exit, so on
|
||||||
|
// failure this only reports the exit code, not the aws CLI's error text.
|
||||||
|
_, _, err := execInPod(ctx, clientSet, cfg, ns, s3Client, s3ClientName,
|
||||||
|
"aws", "s3", "cp", walObjectURI(src), walObjectURI(dst))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "forging %s -> %s", src, dst)
|
||||||
|
}
|
||||||
|
objectExists := func(name string) bool {
|
||||||
|
out, _, err := execInPod(ctx, clientSet, cfg, ns, s3Client, s3ClientName,
|
||||||
|
"aws", "s3", "ls", walObjectURI(name))
|
||||||
|
return err == nil && strings.TrimSpace(out) != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
By("archiving a real WAL on the primary and learning its name")
|
||||||
|
_, _, err := execInPod(ctx, clientSet, cfg, ns, primary, postgresContainer,
|
||||||
|
"psql", "-tAc", "CHECKPOINT")
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "CHECKPOINT on the primary failed")
|
||||||
|
out, _, err := execInPod(ctx, clientSet, cfg, ns, primary, postgresContainer,
|
||||||
|
"psql", "-tAc", "SELECT pg_walfile_name(pg_switch_wal())")
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "switching WAL on the primary failed")
|
||||||
|
latestWAL := strings.TrimSpace(out)
|
||||||
|
Expect(latestWAL).To(HavePrefix(walLogDir),
|
||||||
|
"the freshly bootstrapped cluster should still be on the first WAL log")
|
||||||
|
|
||||||
|
By("waiting for the archived WAL to land on the object store")
|
||||||
|
Eventually(func() bool {
|
||||||
|
return objectExists(latestWAL + ".gz")
|
||||||
|
}).WithTimeout(2 * time.Minute).WithPolling(5 * time.Second).Should(BeTrue())
|
||||||
|
|
||||||
|
By("forging WAL segments #1 to #5 from the archived WAL")
|
||||||
|
for n := 1; n <= 5; n++ {
|
||||||
|
forge(latestWAL+".gz", walFile(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
By("ensuring the spool directory is empty on the standby")
|
||||||
|
purgeSpool()
|
||||||
|
|
||||||
|
// #1: served fresh; #2 and #3 prefetched into the spool; flag unset.
|
||||||
|
By("requesting WAL #1: #1 restored, #2 and #3 prefetched")
|
||||||
|
Expect(restore(walFile(1))).To(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(existsIn(pgWalPath, walFile(1))).To(BeTrue(), "#1 in pg_wal")
|
||||||
|
g.Expect(existsIn(spoolDirectory, walFile(2))).To(BeTrue(), "#2 in spool")
|
||||||
|
g.Expect(existsIn(spoolDirectory, walFile(3))).To(BeTrue(), "#3 in spool")
|
||||||
|
g.Expect(flagSet()).To(BeFalse(), "end-of-wal-stream unset")
|
||||||
|
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
// #2: served from the spool; #3 stays prefetched; no new prefetch; flag unset.
|
||||||
|
By("requesting WAL #2: served from the spool, #3 still prefetched")
|
||||||
|
Expect(restore(walFile(2))).To(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(existsIn(pgWalPath, walFile(2))).To(BeTrue(), "#2 in pg_wal")
|
||||||
|
g.Expect(existsIn(spoolDirectory, walFile(3))).To(BeTrue(), "#3 in spool")
|
||||||
|
g.Expect(flagSet()).To(BeFalse(), "end-of-wal-stream unset")
|
||||||
|
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
// #3: served from the spool; spool now empty; flag unset.
|
||||||
|
By("requesting WAL #3: served from the spool, spool now empty")
|
||||||
|
Expect(restore(walFile(3))).To(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(existsIn(pgWalPath, walFile(3))).To(BeTrue(), "#3 in pg_wal")
|
||||||
|
g.Expect(spoolSegments()).To(Equal(0), "no WAL segments in spool")
|
||||||
|
g.Expect(flagSet()).To(BeFalse(), "end-of-wal-stream unset")
|
||||||
|
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
// #4: served fresh; #5 prefetched; #6 absent so end-of-wal-stream is set.
|
||||||
|
By("requesting WAL #4: #4 restored, #5 prefetched, end-of-wal-stream set")
|
||||||
|
Expect(restore(walFile(4))).To(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(existsIn(pgWalPath, walFile(4))).To(BeTrue(), "#4 in pg_wal")
|
||||||
|
g.Expect(existsIn(spoolDirectory, walFile(5))).To(BeTrue(), "#5 in spool")
|
||||||
|
g.Expect(flagSet()).To(BeTrue(), "end-of-wal-stream set (#6 absent)")
|
||||||
|
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
By("forging WAL segment #6 on the object store")
|
||||||
|
forge(latestWAL+".gz", walFile(6))
|
||||||
|
|
||||||
|
// #5: served from the spool; flag untouched (served before it is checked).
|
||||||
|
By("requesting WAL #5: served from the spool, end-of-wal-stream still set")
|
||||||
|
Expect(restore(walFile(5))).To(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(existsIn(pgWalPath, walFile(5))).To(BeTrue(), "#5 in pg_wal")
|
||||||
|
g.Expect(spoolSegments()).To(Equal(0), "no WAL segments in spool")
|
||||||
|
g.Expect(flagSet()).To(BeTrue(), "end-of-wal-stream still set")
|
||||||
|
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
// #6 (first): flag is set, so the request fails fast (exit 1) and the
|
||||||
|
// flag is consumed, leaving an empty spool.
|
||||||
|
By("requesting WAL #6: fails fast on the end-of-wal-stream flag, spool cleared")
|
||||||
|
restoreErr := restore(walFile(6))
|
||||||
|
var exitErr executil.CodeExitError
|
||||||
|
Expect(errors.As(restoreErr, &exitErr)).To(BeTrue(),
|
||||||
|
"expected a CodeExitError, got %T: %v", restoreErr, restoreErr)
|
||||||
|
Expect(exitErr.ExitStatus()).To(Equal(1), "exit code should be 1")
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(existsIn(pgWalPath, walFile(6))).To(BeFalse(), "#6 not restored")
|
||||||
|
g.Expect(spoolSegments()).To(Equal(0), "no WAL segments in spool")
|
||||||
|
g.Expect(flagSet()).To(BeFalse(), "end-of-wal-stream consumed")
|
||||||
|
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||||
|
|
||||||
|
// #6 (second): now present, restored; #7 and #8 absent so the flag is
|
||||||
|
// set again.
|
||||||
|
By("requesting WAL #6 again: #6 restored, end-of-wal-stream set again")
|
||||||
|
Expect(restore(walFile(6))).To(Succeed())
|
||||||
|
Eventually(func(g Gomega) {
|
||||||
|
g.Expect(existsIn(pgWalPath, walFile(6))).To(BeTrue(), "#6 in pg_wal")
|
||||||
|
g.Expect(spoolSegments()).To(Equal(0), "no WAL segments in spool")
|
||||||
|
g.Expect(flagSet()).To(BeTrue(), "end-of-wal-stream set (#7/#8 absent)")
|
||||||
|
}).WithTimeout(time.Minute).WithPolling(2 * time.Second).Should(Succeed())
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -8396,9 +8396,9 @@ send@~0.19.0, send@~0.19.1:
|
|||||||
statuses "~2.0.2"
|
statuses "~2.0.2"
|
||||||
|
|
||||||
serialize-javascript@>=7.0.5, serialize-javascript@^6.0.0, serialize-javascript@^6.0.1:
|
serialize-javascript@>=7.0.5, serialize-javascript@^6.0.0, serialize-javascript@^6.0.1:
|
||||||
version "7.0.6"
|
version "7.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-7.0.6.tgz#f2f20c8af0757e4d8fa329d0210636da0682ddef"
|
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-7.0.7.tgz#06ec40576d4cea96d68010a534520bff1f948a72"
|
||||||
integrity sha512-ATTK5Q4gFVg0YDp1my2vqygyvhcklD/UV5GIlYHooGTn/NogJqIzpetkD6E5kmuVULqz/S9inUL25XcAgDRJQg==
|
integrity sha512-YAy8Od6KV+uuwUuU50np8fGB/Aues6Y0nAhA9y/hId74PlKUcme4pXcBD46NWKr1Q4osN/iseZ17YqO1XfmI8g==
|
||||||
|
|
||||||
serve-handler@^6.1.7:
|
serve-handler@^6.1.7:
|
||||||
version "6.1.7"
|
version "6.1.7"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user