mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-09-06 15:02:21 +02:00
Compare commits
7 Commits
c9cb94929e
...
70eafca535
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70eafca535 | ||
|
|
fb3f0f9dab | ||
|
|
fe82a311ec | ||
|
|
5e62b7ef88 | ||
|
|
806f47b483 | ||
|
|
7dab33a923 | ||
|
|
f386c2d85a |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -8,12 +8,13 @@ permissions: read-all
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.CI_RUNNERS || 'ubuntu-latest' }}
|
||||||
permissions:
|
permissions:
|
||||||
packages: write
|
packages: write
|
||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Cleanup Disk
|
- name: Cleanup Disk
|
||||||
|
if: vars.CI_RUNNERS == '' || vars.CI_RUNNERS == 'ubuntu-latest'
|
||||||
uses: jlumbroso/free-disk-space@v1.3.1
|
uses: jlumbroso/free-disk-space@v1.3.1
|
||||||
with:
|
with:
|
||||||
android: true
|
android: true
|
||||||
@ -23,6 +24,7 @@ jobs:
|
|||||||
large-packages: false
|
large-packages: false
|
||||||
swap-storage: false
|
swap-storage: false
|
||||||
- name: Cleanup docker cache
|
- name: Cleanup docker cache
|
||||||
|
if: vars.CI_RUNNERS == '' || vars.CI_RUNNERS == 'ubuntu-latest'
|
||||||
run: |
|
run: |
|
||||||
echo "-------------Disk info before cleanup----------------"
|
echo "-------------Disk info before cleanup----------------"
|
||||||
df -h
|
df -h
|
||||||
@ -32,7 +34,7 @@ jobs:
|
|||||||
df -h
|
df -h
|
||||||
echo "-----------------------------------------------------"
|
echo "-----------------------------------------------------"
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.1
|
||||||
# We need the full history for the commitlint task
|
# We need the full history for the commitlint task
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|||||||
6
.github/workflows/publish-docs.yml
vendored
6
.github/workflows/publish-docs.yml
vendored
@ -20,12 +20,12 @@ permissions: read-all
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.CI_RUNNERS || 'ubuntu-latest' }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.1
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v7
|
uses: actions/setup-node@v7
|
||||||
@ -60,7 +60,7 @@ jobs:
|
|||||||
name: github-pages
|
name: github-pages
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.CI_RUNNERS || 'ubuntu-latest' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
id: deployment
|
||||||
|
|||||||
4
.github/workflows/release-please.yml
vendored
4
.github/workflows/release-please.yml
vendored
@ -9,7 +9,7 @@ permissions: read-all
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-please:
|
release-please:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.CI_RUNNERS || 'ubuntu-latest' }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
@ -19,7 +19,7 @@ jobs:
|
|||||||
# We'll use the cli until there's a fix for
|
# We'll use the cli until there's a fix for
|
||||||
# https://github.com/googleapis/release-please/issues/2280.
|
# https://github.com/googleapis/release-please/issues/2280.
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.1
|
||||||
- name: Install node
|
- name: Install node
|
||||||
uses: actions/setup-node@v7
|
uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
|
|||||||
4
.github/workflows/release-publish.yml
vendored
4
.github/workflows/release-publish.yml
vendored
@ -7,13 +7,13 @@ permissions: read-all
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-publish-artifacts:
|
release-publish-artifacts:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ vars.CI_RUNNERS || 'ubuntu-latest' }}
|
||||||
permissions:
|
permissions:
|
||||||
packages: write
|
packages: write
|
||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v7.0.0
|
uses: actions/checkout@v7.0.1
|
||||||
- name: Install QEMU static binaries
|
- name: Install QEMU static binaries
|
||||||
uses: docker/setup-qemu-action@v4
|
uses: docker/setup-qemu-action@v4
|
||||||
- name: Install Task
|
- name: Install Task
|
||||||
|
|||||||
@ -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-07-20)
|
## [0.13.1](https://github.com/cloudnative-pg/plugin-barman-cloud/compare/v0.13.0...v0.13.1) (2026-07-21)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
@ -23,6 +23,7 @@
|
|||||||
* 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)
|
* 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))
|
||||||
|
* **walrestore:** Serve pg_rewind without prefetching and flag machinery ([#1007](https://github.com/cloudnative-pg/plugin-barman-cloud/issues/1007)) ([fb3f0f9](https://github.com/cloudnative-pg/plugin-barman-cloud/commit/fb3f0f9dabba85d87af85418d58b2f8224ed6305))
|
||||||
|
|
||||||
## [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)
|
||||||
|
|
||||||
|
|||||||
@ -2,4 +2,4 @@
|
|||||||
# responsible for code in a repository. For details, please refer to
|
# responsible for code in a repository. For details, please refer to
|
||||||
# https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-code-owners
|
# https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-code-owners
|
||||||
|
|
||||||
* @cloudnative-pg/maintainers
|
* @leonardoce @mnencia @gbartolini @fcanovai @armru @NiccoloFei
|
||||||
|
|||||||
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: 7431c24907de3c6b1516114c8990d4f8d23d92cd
|
DAGGER_SPELLCHECK_SHA: f7187c307f2ba79290efbfff5ce436b956162c53
|
||||||
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: 7431c24907de3c6b1516114c8990d4f8d23d92cd
|
DAGGER_COMMITLINT_SHA: f7187c307f2ba79290efbfff5ce436b956162c53
|
||||||
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: 7431c24907de3c6b1516114c8990d4f8d23d92cd
|
DAGGER_UNCOMMITTED_SHA: f7187c307f2ba79290efbfff5ce436b956162c53
|
||||||
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: 7431c24907de3c6b1516114c8990d4f8d23d92cd
|
DAGGER_CRDGENREF_SHA: f7187c307f2ba79290efbfff5ce436b956162c53
|
||||||
# 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:
|
||||||
@ -383,7 +383,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: 7431c24907de3c6b1516114c8990d4f8d23d92cd
|
DAGGER_CONTROLLER_GEN_SHA: f7187c307f2ba79290efbfff5ce436b956162c53
|
||||||
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}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
|
||||||
"github.com/cloudnative-pg/barman-cloud/pkg/archiver"
|
"github.com/cloudnative-pg/barman-cloud/pkg/archiver"
|
||||||
barmanCommand "github.com/cloudnative-pg/barman-cloud/pkg/command"
|
barmanCommand "github.com/cloudnative-pg/barman-cloud/pkg/command"
|
||||||
barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials"
|
barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials"
|
||||||
@ -249,9 +250,11 @@ func (w WALServiceImplementation) Restore(
|
|||||||
"Restoring WAL file",
|
"Restoring WAL file",
|
||||||
"objectStore", objectStore.Name,
|
"objectStore", objectStore.Name,
|
||||||
"serverName", serverName,
|
"serverName", serverName,
|
||||||
"walName", walName)
|
"walName", walName,
|
||||||
|
"mode", request.GetMode())
|
||||||
return &wal.WALRestoreResult{}, w.restoreFromBarmanObjectStore(
|
return &wal.WALRestoreResult{}, w.restoreFromBarmanObjectStore(
|
||||||
ctx, configuration.Cluster, &objectStore, serverName, walName, destinationPath)
|
ctx, configuration.Cluster, &objectStore, serverName, walName, destinationPath,
|
||||||
|
request.GetMode() == wal.WALRestoreRequest_MODE_REWIND)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveRestoreObjectStore selects the object store and server name to use when
|
// resolveRestoreObjectStore selects the object store and server name to use when
|
||||||
@ -288,6 +291,7 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore(
|
|||||||
serverName string,
|
serverName string,
|
||||||
walName string,
|
walName string,
|
||||||
destinationPath string,
|
destinationPath string,
|
||||||
|
rewindMode bool,
|
||||||
) error {
|
) error {
|
||||||
contextLogger := log.FromContext(ctx)
|
contextLogger := log.FromContext(ctx)
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
@ -319,6 +323,20 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore(
|
|||||||
return fmt.Errorf("while creating the restorer: %w", err)
|
return fmt.Errorf("while creating the restorer: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A flag left over from a normal-recovery invocation that ran before this pod
|
||||||
|
// was demoted must not survive into a pg_rewind restore: the flag machinery
|
||||||
|
// does not apply while restoring on behalf of pg_rewind (see
|
||||||
|
// shouldUseEndOfWALStreamFlag below), so it is never checked here, but left
|
||||||
|
// untouched it would resurface and wrongly abort the first normal-recovery
|
||||||
|
// invocation that runs once the rewind is done. This runs unconditionally,
|
||||||
|
// before the spool short-circuit in Step 1, so a request for a WAL file that
|
||||||
|
// happens to already be staged in the spool cannot skip the clear.
|
||||||
|
if rewindMode {
|
||||||
|
if err := clearEndOfWALStreamFlag(walRestorer); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Step 1: check if this WAL file is not already in the spool
|
// Step 1: check if this WAL file is not already in the spool
|
||||||
var wasInSpool bool
|
var wasInSpool bool
|
||||||
if wasInSpool, err = walRestorer.RestoreFromSpool(walName, destinationPath); err != nil {
|
if wasInSpool, err = walRestorer.RestoreFromSpool(walName, destinationPath); err != nil {
|
||||||
@ -331,8 +349,10 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// We skip this step if streaming connection is not available
|
// Step 2: return error if the end-of-wal-stream flag is set.
|
||||||
if isStreamingAvailable(cluster, w.InstanceName) {
|
// We skip this step if the flag machinery does not apply to this invocation
|
||||||
|
useEndOfWALStreamFlag := shouldUseEndOfWALStreamFlag(cluster, w.InstanceName, rewindMode)
|
||||||
|
if useEndOfWALStreamFlag {
|
||||||
if err := checkEndOfWALStreamFlag(walRestorer); err != nil {
|
if err := checkEndOfWALStreamFlag(walRestorer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -340,10 +360,7 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore(
|
|||||||
|
|
||||||
// Step 3: gather the WAL files names to restore. If the required file isn't a regular WAL, we download it directly.
|
// Step 3: gather the WAL files names to restore. If the required file isn't a regular WAL, we download it directly.
|
||||||
var walFilesList []string
|
var walFilesList []string
|
||||||
maxParallel := 1
|
maxParallel := maxWALFilesPerInvocation(barmanConfiguration, rewindMode)
|
||||||
if barmanConfiguration.Wal != nil && barmanConfiguration.Wal.MaxParallel > 1 {
|
|
||||||
maxParallel = barmanConfiguration.Wal.MaxParallel
|
|
||||||
}
|
|
||||||
if IsWALFile(walName) {
|
if IsWALFile(walName) {
|
||||||
// If this is a regular WAL file, we try to prefetch
|
// If this is a regular WAL file, we try to prefetch
|
||||||
if walFilesList, err = gatherWALFilesToRestore(walName, maxParallel); err != nil {
|
if walFilesList, err = gatherWALFilesToRestore(walName, maxParallel); err != nil {
|
||||||
@ -365,9 +382,9 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore(
|
|||||||
return classifyWALRestoreError(walStatus[0].WalName, walStatus[0].Err)
|
return classifyWALRestoreError(walStatus[0].WalName, walStatus[0].Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We skip this step if streaming connection is not available
|
// We skip this step if the flag machinery does not apply to this invocation
|
||||||
endOfWALStream := isEndOfWALStream(walStatus)
|
endOfWALStream := isEndOfWALStream(walStatus)
|
||||||
if isStreamingAvailable(cluster, w.InstanceName) && endOfWALStream {
|
if useEndOfWALStreamFlag && endOfWALStream {
|
||||||
contextLogger.Info(
|
contextLogger.Info(
|
||||||
"Set end-of-wal-stream flag as one of the WAL files to be prefetched was not found")
|
"Set end-of-wal-stream flag as one of the WAL files to be prefetched was not found")
|
||||||
|
|
||||||
@ -415,6 +432,38 @@ func (w WALServiceImplementation) SetFirstRequired(
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maxWALFilesPerInvocation returns how many WAL files a single restore
|
||||||
|
// invocation is allowed to fetch, the requested one included. Prefetching is
|
||||||
|
// disabled when restoring on behalf of pg_rewind, which walks the WAL
|
||||||
|
// backward: the following segments would never be requested, and past the end
|
||||||
|
// of the timeline they do not even exist
|
||||||
|
func maxWALFilesPerInvocation(barmanConfiguration *barmanapi.BarmanObjectStoreConfiguration, rewindMode bool) int {
|
||||||
|
if rewindMode {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if barmanConfiguration.Wal != nil && barmanConfiguration.Wal.MaxParallel > 1 {
|
||||||
|
return barmanConfiguration.Wal.MaxParallel
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// shouldUseEndOfWALStreamFlag returns true when the end-of-wal-stream flag
|
||||||
|
// machinery applies to the current invocation. The flag makes the following
|
||||||
|
// invocation fail, so that PostgreSQL stops polling the WAL archive and
|
||||||
|
// switches to streaming replication. It does not apply when no streaming
|
||||||
|
// connection is available, nor when restoring on behalf of pg_rewind:
|
||||||
|
// pg_rewind cannot fall back to streaming replication, and a stale flag would
|
||||||
|
// make it abort on a segment that is available in the archive
|
||||||
|
func shouldUseEndOfWALStreamFlag(cluster *cnpgv1.Cluster, podName string, rewindMode bool) bool {
|
||||||
|
if rewindMode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return isStreamingAvailable(cluster, podName)
|
||||||
|
}
|
||||||
|
|
||||||
// isStreamingAvailable checks if this pod can replicate via streaming connection.
|
// isStreamingAvailable checks if this pod can replicate via streaming connection.
|
||||||
func isStreamingAvailable(cluster *cnpgv1.Cluster, podName string) bool {
|
func isStreamingAvailable(cluster *cnpgv1.Cluster, podName string) bool {
|
||||||
if cluster == nil {
|
if cluster == nil {
|
||||||
@ -491,6 +540,22 @@ func checkEndOfWALStreamFlag(walRestorer *barmanRestorer.WALRestorer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clearEndOfWALStreamFlag removes the end-of-wal-stream flag, if present, without
|
||||||
|
// treating it as an error. It is used instead of checkEndOfWALStreamFlag when
|
||||||
|
// restoring on behalf of pg_rewind, which must not abort on a flag it did not
|
||||||
|
// set itself.
|
||||||
|
func clearEndOfWALStreamFlag(walRestorer *barmanRestorer.WALRestorer) error {
|
||||||
|
contain, err := walRestorer.IsEndOfWALStream()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if contain {
|
||||||
|
return walRestorer.ResetEndOfWalStream()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// isEndOfWALStream returns true if one of the downloads has returned
|
// isEndOfWALStream returns true if one of the downloads has returned
|
||||||
// a file-not-found error.
|
// a file-not-found error.
|
||||||
func isEndOfWALStream(results []barmanRestorer.Result) bool {
|
func isEndOfWALStream(results []barmanRestorer.Result) bool {
|
||||||
|
|||||||
@ -20,6 +20,10 @@ SPDX-License-Identifier: Apache-2.0
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
|
||||||
|
barmanRestorer "github.com/cloudnative-pg/barman-cloud/pkg/restorer"
|
||||||
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -96,3 +100,80 @@ var _ = Describe("resolveRestoreObjectStore", func() {
|
|||||||
"cluster-server", "cluster-store"),
|
"cluster-server", "cluster-store"),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = Describe("maxWALFilesPerInvocation", func() {
|
||||||
|
configWithMaxParallel := func(maxParallel int) *barmanapi.BarmanObjectStoreConfiguration {
|
||||||
|
return &barmanapi.BarmanObjectStoreConfiguration{
|
||||||
|
Wal: &barmanapi.WalBackupConfiguration{MaxParallel: maxParallel},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DescribeTable(
|
||||||
|
"computes how many WAL files a single invocation may fetch",
|
||||||
|
func(cfg *barmanapi.BarmanObjectStoreConfiguration, rewindMode bool, want int) {
|
||||||
|
Expect(maxWALFilesPerInvocation(cfg, rewindMode)).To(Equal(want))
|
||||||
|
},
|
||||||
|
|
||||||
|
Entry("no WAL configuration", &barmanapi.BarmanObjectStoreConfiguration{}, false, 1),
|
||||||
|
Entry("parallel restore configured", configWithMaxParallel(8), false, 8),
|
||||||
|
|
||||||
|
// pg_rewind walks the timeline backwards: prefetching must stay off no
|
||||||
|
// matter what the object store configuration asks for
|
||||||
|
Entry("rewind mode overrides the configured parallelism", configWithMaxParallel(8), true, 1),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
var _ = Describe("shouldUseEndOfWALStreamFlag", func() {
|
||||||
|
clusterWithPrimary := func(currentPrimary string) *cnpgv1.Cluster {
|
||||||
|
return &cnpgv1.Cluster{
|
||||||
|
Status: cnpgv1.ClusterStatus{CurrentPrimary: currentPrimary},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DescribeTable(
|
||||||
|
"decides whether the end-of-wal-stream flag machinery applies",
|
||||||
|
func(cluster *cnpgv1.Cluster, podName string, rewindMode bool, want bool) {
|
||||||
|
Expect(shouldUseEndOfWALStreamFlag(cluster, podName, rewindMode)).To(Equal(want))
|
||||||
|
},
|
||||||
|
|
||||||
|
Entry("replica with streaming available", clusterWithPrimary("cluster-1"), "cluster-2", false, true),
|
||||||
|
Entry("primary cannot stream from anyone", clusterWithPrimary("cluster-1"), "cluster-1", false, false),
|
||||||
|
|
||||||
|
// pg_rewind cannot fall back to streaming replication: the flag machinery
|
||||||
|
// must stay off even where a standby would use it
|
||||||
|
Entry("rewind mode wins over streaming availability", clusterWithPrimary("cluster-1"), "cluster-2", true, false),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
var _ = Describe("clearEndOfWALStreamFlag", func() {
|
||||||
|
newRestorer := func() *barmanRestorer.WALRestorer {
|
||||||
|
restorer, err := barmanRestorer.New(context.Background(), nil, GinkgoT().TempDir())
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
return restorer
|
||||||
|
}
|
||||||
|
|
||||||
|
It("is a no-op when the flag is not set", func() {
|
||||||
|
restorer := newRestorer()
|
||||||
|
|
||||||
|
Expect(clearEndOfWALStreamFlag(restorer)).To(Succeed())
|
||||||
|
|
||||||
|
isEOS, err := restorer.IsEndOfWALStream()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(isEOS).To(BeFalse())
|
||||||
|
})
|
||||||
|
|
||||||
|
// Regression guard: a flag left over from a normal-recovery invocation that
|
||||||
|
// ran before this pod was demoted must not survive a pg_rewind restore, or
|
||||||
|
// it would resurface and wrongly abort the first normal-recovery invocation
|
||||||
|
// that runs once the rewind is done.
|
||||||
|
It("removes a pre-existing flag without returning an error", func() {
|
||||||
|
restorer := newRestorer()
|
||||||
|
Expect(restorer.SetEndOfWALStream()).To(Succeed())
|
||||||
|
|
||||||
|
Expect(clearEndOfWALStreamFlag(restorer)).To(Succeed())
|
||||||
|
|
||||||
|
isEOS, err := restorer.IsEndOfWALStream()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(isEOS).To(BeFalse())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@ -121,8 +121,8 @@ func newS3ClientDeployment(namespace string) *appsv1.Deployment {
|
|||||||
{
|
{
|
||||||
Name: s3ClientName,
|
Name: s3ClientName,
|
||||||
// renovate: datasource=docker depName=amazon/aws-cli versioning=docker
|
// renovate: datasource=docker depName=amazon/aws-cli versioning=docker
|
||||||
// Version: 2.36.2
|
// Version: 2.36.3
|
||||||
Image: "docker.io/amazon/aws-cli@sha256:964336bffb17b82d2e84a2526b0672e70a2c881544e1a281acaca1d9aa41b536",
|
Image: "docker.io/amazon/aws-cli@sha256:bdd02067a00c354684086071b475955c54caa7bd88b851aac99a51326fe19652",
|
||||||
Command: []string{"sleep", "infinity"},
|
Command: []string{"sleep", "infinity"},
|
||||||
Env: []corev1.EnvVar{
|
Env: []corev1.EnvVar{
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user