Compare commits

...

15 Commits

Author SHA1 Message Date
Armando Ruocco
bba751a17c test: cover the empty WAL archive decision in both hooks
Add unit coverage for the WAL archive and restore-job decision helpers.
The tables pin the version-skew contract: when the operator sets the
decision it overrides both the Cluster annotation and, for archiving, the
on-disk marker file, while a nil decision (an operator that predates the
field) reproduces the previous annotation-based behavior.

Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
2026-07-21 17:15:16 +02:00
Armando Ruocco
6fddc14398 refactor: extract the empty WAL archive decision into a helper
The WAL archive hook and the restore job hook each derived, inline,
whether to verify the archive destination before proceeding. Pull each
decision into a small function so the operator-decision-versus-fallback
logic can be exercised on its own. Behavior is unchanged: archiving still
fails on a marker-file stat error, and restore still falls back to the
Cluster annotation alone.

Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
2026-07-21 17:07:00 +02:00
Marco Nenciarini
7efb2cdf56 feat: honor the operator's check_empty_wal_archive decision
Archive() and the restore job hook each re-derived, on their own,
whether to verify the WAL archive destination is empty, by reading a
Cluster annotation and, for Archive, an on-disk marker file. That
decision belongs to the operator, which already tracks both the
annotation and the marker file's lifecycle.

Honor cnpg-i's new WALArchiveRequest/RestoreRequest field
CheckEmptyWalArchive when the operator sets it: obey it directly,
without re-inspecting the marker file. Only fall back to the previous
annotation-and-marker-file logic when talking to an operator that
predates this field.

Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
2026-07-21 17:07:00 +02:00
Marco Nenciarini
1d777435d0
ci: run image publish in a separate parallel job (#1026)
Neither task depends on the other's output: task ci runs lint, tests,
e2e, and docs, while task publish builds and pushes the multi-arch
images. Running them as sequential steps in one job only adds their
durations. Splitting publish into its own job lets it run alongside ci
instead, and lets each job carry only the permissions it actually needs:
ci never writes to the registry, and neither task touches repository
contents, so only packages: write on the publish job remains.

QEMU is only needed for publish, since it's the only job that builds
non-native (arm64) platforms; ci's e2e-ephemeral image build is
amd64-only. The disk cleanup steps aren't needed for publish either: it
only builds two lean multi-arch images, well within the free disk space
available even on the default ubuntu-latest runner.

Note that publishing testing images no longer waits on ci passing, since
gating it away would remove the parallelism this is meant to gain.

Note: main's required status checks are currently ["DCO", "ci"]. A
failure in the new publish job will no longer block merging a PR, since
it isn't in that list (today it does, since publishing is a step inside
the required ci job). Flagging for a decision on whether publish should
be added as a required check.

Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Signed-off-by: Niccolò Fei <niccolo.fei@enterprisedb.com>
Co-authored-by: Niccolò Fei <niccolo.fei@enterprisedb.com>
2026-07-21 17:03:39 +02:00
Armando Ruocco
fb3f0f9dab
fix(walrestore): serve pg_rewind without prefetching and flag machinery (#1007)
When a demoted primary rejoins the cluster after a failover, the
instance manager runs `pg_rewind --restore-target-wal`, and the
resulting `restore_command` invocations are served by this sidecar
exactly as if an instance in recovery were asking. pg_rewind walks the
timeline backwards, fetches every WAL file it needs exactly once, and
treats any restore failure as fatal, so two optimizations meant for
recovery break it: prefetching the following segments is wasted work
that, past the end of the timeline, is guaranteed to end in an archive
miss, and the end-of-wal-stream flag recorded by that miss makes a later
invocation fail without contacting the object store, on a segment the
archive actually has, aborting the whole rewind.

The restore request now carries the context it is made in
(cloudnative-pg/cnpg-i#351). When it says `MODE_REWIND`, the sidecar
restores exactly the requested file: no prefetching, no
end-of-wal-stream flag check, no flag recording. Requests from operators
predating the field keep the current behavior.

This is the plugin-side counterpart of
cloudnative-pg/cloudnative-pg#11204. The cnpg-i dependency points to a
pseudo-version of the protocol pull request and will move to the next
tagged release once it is available.

Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Co-authored-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
2026-07-21 15:01:51 +02:00
renovate[bot]
fe82a311ec
chore(deps): update amazon/aws-cli docker tag to v2.36.3 (#1027)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-21 09:53:34 +02:00
renovate[bot]
5e62b7ef88
chore(deps): update all cloudnative-pg daggerverse dependencies to f7187c3 (#1028)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-21 09:22:11 +02:00
Gabriele Bartolini
806f47b483
chore: expand account names in CODEOWNERS (#1016)
Add @NiccoloFei as contributor

Closes #1015

Signed-off-by: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com>
2026-07-21 08:21:32 +10:00
renovate[bot]
7dab33a923
chore(deps): update actions/checkout action to v7.0.1 (#1024)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | patch | `v7.0.0` → `v7.0.1` |

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-20 18:17:40 +02:00
Marco Nenciarini
f386c2d85a
ci: make runner labels configurable via CI_RUNNERS variable (#1023)
Switch all workflow jobs from a hardcoded ubuntu-latest to ${{
vars.CI_RUNNERS || 'ubuntu-latest' }}, so runner sizing can be changed
via the CI_RUNNERS organization/repository variable without editing
workflow files.

The cloudnative-pg organization CI_RUNNERS variable is already set to
ubuntu-latest-16-cores.

Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
2026-07-20 18:17:21 +02:00
renovate[bot]
98537c4d0e
fix(deps): update github.com/cloudnative-pg/barman-cloud digest to 950b0f5 (#1022)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[github.com/cloudnative-pg/barman-cloud](https://redirect.github.com/cloudnative-pg/barman-cloud)
| require | digest | `43158c2` → `950b0f5` |

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-20 17:47:21 +02:00
renovate[bot]
5aa67b0951
chore(deps): update fsouza/fake-gcs-server docker tag to v1.55.1 (#1018)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
|
[fsouza/fake-gcs-server](https://redirect.github.com/fsouza/fake-gcs-server)
| patch | `1.55.0` → `1.55.1` |

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-20 17:46:48 +02:00
renovate[bot]
ccc950dd9f
chore(deps): update amazon/aws-cli docker tag to v2.36.2 (#1014)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| amazon/aws-cli | patch | `2.36.1` → `2.36.2` |

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
2026-07-20 17:10:20 +02:00
renovate[bot]
13450a370d
fix(deps): update module github.com/cloudnative-pg/cnpg-i to v0.6.0 (#1021)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[github.com/cloudnative-pg/cnpg-i](https://redirect.github.com/cloudnative-pg/cnpg-i)
| `v0.5.0` → `v0.6.0` |
![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fcloudnative-pg%2fcnpg-i/v0.6.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fcloudnative-pg%2fcnpg-i/v0.5.0/v0.6.0?slim=true)
|

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-20 17:08:30 +02:00
renovate[bot]
0d75cb9ca2
chore(deps): lock file maintenance (#1019)
This PR contains the following updates:

| Update | Change |
|---|---|
| lockFileMaintenance | All locks refreshed |

🔧 This Pull Request updates lock files to use the latest dependency
versions.

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - "before 4am on monday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/cloudnative-pg/plugin-barman-cloud).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNjUuMSIsInVwZGF0ZWRJblZlciI6IjQzLjI2NS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJhdXRvbWF0ZWQiLCJuby1pc3N1ZSJdfQ==-->

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
2026-07-20 17:00:18 +02:00
16 changed files with 567 additions and 189 deletions

View File

@ -6,14 +6,18 @@ on:
permissions: read-all permissions: read-all
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs: jobs:
ci: ci:
runs-on: ubuntu-latest runs-on: ${{ vars.CI_RUNNERS || 'ubuntu-latest' }}
permissions: permissions:
packages: write contents: read
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 +27,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,13 +37,11 @@ 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
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Install QEMU static binaries
uses: docker/setup-qemu-action@v4
- name: Install Task - name: Install Task
uses: arduino/setup-task@v3.0.0 uses: arduino/setup-task@v3.0.0
- name: Install Dagger - name: Install Dagger
@ -50,6 +53,27 @@ jobs:
- name: Run CI task - name: Run CI task
run: | run: |
task ci task ci
publish:
runs-on: ${{ vars.CI_RUNNERS || 'ubuntu-latest' }}
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install QEMU static binaries
uses: docker/setup-qemu-action@v4
- name: Install Task
uses: arduino/setup-task@v3.0.0
- name: Install Dagger
env:
# renovate: datasource=github-tags depName=dagger/dagger versioning=semver
DAGGER_VERSION: 0.21.7
run: |
curl -L https://dl.dagger.io/dagger/install.sh | BIN_DIR=$HOME/.local/bin sh
- name: Write manifest - name: Write manifest
run: | run: |
task manifest task manifest

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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}

4
go.mod
View File

@ -5,9 +5,9 @@ go 1.26.4
require ( require (
github.com/cert-manager/cert-manager v1.21.0 github.com/cert-manager/cert-manager v1.21.0
github.com/cloudnative-pg/api v1.30.0 github.com/cloudnative-pg/api v1.30.0
github.com/cloudnative-pg/barman-cloud v0.5.2-0.20260709152604-43158c204df1 github.com/cloudnative-pg/barman-cloud v0.5.2-0.20260720143032-950b0f57e122
github.com/cloudnative-pg/cloudnative-pg v1.30.0 github.com/cloudnative-pg/cloudnative-pg v1.30.0
github.com/cloudnative-pg/cnpg-i v0.5.0 github.com/cloudnative-pg/cnpg-i v0.6.0
github.com/cloudnative-pg/cnpg-i-machinery v0.4.2 github.com/cloudnative-pg/cnpg-i-machinery v0.4.2
github.com/cloudnative-pg/machinery v0.5.0 github.com/cloudnative-pg/machinery v0.5.0
github.com/onsi/ginkgo/v2 v2.32.0 github.com/onsi/ginkgo/v2 v2.32.0

8
go.sum
View File

@ -20,12 +20,12 @@ 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/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudnative-pg/api v1.30.0 h1:L8hnvV/tPEQA1xYEi41FUBFA7FUNVGju8+SlgFlDDjI= github.com/cloudnative-pg/api v1.30.0 h1:L8hnvV/tPEQA1xYEi41FUBFA7FUNVGju8+SlgFlDDjI=
github.com/cloudnative-pg/api v1.30.0/go.mod h1:XrKBbOWObL33si0FNuwX4uHNf5JShiZyOUqd6LxbJQo= github.com/cloudnative-pg/api v1.30.0/go.mod h1:XrKBbOWObL33si0FNuwX4uHNf5JShiZyOUqd6LxbJQo=
github.com/cloudnative-pg/barman-cloud v0.5.2-0.20260709152604-43158c204df1 h1:+AV67yFPqnwmHQ5PIYkAaJUDsOrrwJCvH+J1JzHXyQc= github.com/cloudnative-pg/barman-cloud v0.5.2-0.20260720143032-950b0f57e122 h1:NuOztBdp+bUr/xYtaAw8o/x880hvWDRhJGl+R1YsZNw=
github.com/cloudnative-pg/barman-cloud v0.5.2-0.20260709152604-43158c204df1/go.mod h1:ZQLkdpk44FW5/BGWzABTOEcV9qPbwC+rbdscg2I8mBI= github.com/cloudnative-pg/barman-cloud v0.5.2-0.20260720143032-950b0f57e122/go.mod h1:ZQLkdpk44FW5/BGWzABTOEcV9qPbwC+rbdscg2I8mBI=
github.com/cloudnative-pg/cloudnative-pg v1.30.0 h1:fnhVq44xXx97MNiuvJsPrX1vSjYbgdyBK5MSGfdHdp0= github.com/cloudnative-pg/cloudnative-pg v1.30.0 h1:fnhVq44xXx97MNiuvJsPrX1vSjYbgdyBK5MSGfdHdp0=
github.com/cloudnative-pg/cloudnative-pg v1.30.0/go.mod h1:QkolwBOWZ+GvAiJt6KpDSymwkpf0K19/p4Q6MQlTM8U= github.com/cloudnative-pg/cloudnative-pg v1.30.0/go.mod h1:QkolwBOWZ+GvAiJt6KpDSymwkpf0K19/p4Q6MQlTM8U=
github.com/cloudnative-pg/cnpg-i v0.5.0 h1:/TOzpNT6cwNgrpftTtrnLKdoHgMwd+88vZgXjlVgXeE= github.com/cloudnative-pg/cnpg-i v0.6.0 h1:LA//DLkFOLIjU0ASOpFkydZhGir9IAIDfgSsTTX9IpU=
github.com/cloudnative-pg/cnpg-i v0.5.0/go.mod h1:7Gh4+UzhBpGhr4DreB1GN9wGYfvxwXCXZUyVt3zE/3I= github.com/cloudnative-pg/cnpg-i v0.6.0/go.mod h1:4kcpLAj+feMTnh0TVadXRASdVnEhBytNSm/BvktLgmI=
github.com/cloudnative-pg/cnpg-i-machinery v0.4.2 h1:0reS9MtyLYINHXQ/MfxJ9jp39hhBf8e3Qdj+T5Nsq6I= github.com/cloudnative-pg/cnpg-i-machinery v0.4.2 h1:0reS9MtyLYINHXQ/MfxJ9jp39hhBf8e3Qdj+T5Nsq6I=
github.com/cloudnative-pg/cnpg-i-machinery v0.4.2/go.mod h1:gvrKabgxXq0zGthXGucemDdsxakLEQDMxn43M4HLW30= github.com/cloudnative-pg/cnpg-i-machinery v0.4.2/go.mod h1:gvrKabgxXq0zGthXGucemDdsxakLEQDMxn43M4HLW30=
github.com/cloudnative-pg/machinery v0.5.0 h1:hhTnkzn+AiN3NmbjCQ6RXj5rfqV3K6arzq6kdXAzcnQ= github.com/cloudnative-pg/machinery v0.5.0 h1:hhTnkzn+AiN3NmbjCQ6RXj5rfqV3K6arzq6kdXAzcnQ=

View File

@ -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"
@ -155,13 +156,17 @@ func (w WALServiceImplementation) Archive(
return nil, err return nil, err
} }
// Step 2: Check if the archive location is safe to perform archiving // Step 2: Check if the archive location is safe to perform archiving.
checkFileExisting, err := fileutils.FileExists(emptyWalArchiveFile) checkEmptyWalArchive, err := resolveArchiveEmptyWalArchiveCheck(
request.CheckEmptyWalArchive,
configuration.Cluster,
emptyWalArchiveFile,
)
if err != nil { if err != nil {
return nil, fmt.Errorf("while checking for empty wal archive check file %q: %w", emptyWalArchiveFile, err) return nil, err
} }
if utils.IsEmptyWalArchiveCheckEnabled(&configuration.Cluster.ObjectMeta) && checkFileExisting { if checkEmptyWalArchive {
if err := CheckBackupDestination( if err := CheckBackupDestination(
ctx, ctx,
&objectStore.Spec.Configuration, &objectStore.Spec.Configuration,
@ -223,6 +228,31 @@ func (w WALServiceImplementation) Archive(
return &wal.WALArchiveResult{}, nil return &wal.WALArchiveResult{}, nil
} }
// resolveArchiveEmptyWalArchiveCheck reports whether the WAL archive
// destination must be verified before archiving this segment.
//
// The operator owns the marker file's lifecycle, so when it sets the decision
// (non-nil) that value already accounts for the marker and is obeyed as-is. A
// nil value comes from an operator that predates this field, so we fall back to
// the previous logic: the Cluster annotation combined with the on-disk marker
// file.
func resolveArchiveEmptyWalArchiveCheck(
operatorDecision *bool,
cluster *cnpgv1.Cluster,
markerFilePath string,
) (bool, error) {
if operatorDecision != nil {
return *operatorDecision, nil
}
markerFilePresent, err := fileutils.FileExists(markerFilePath)
if err != nil {
return false, fmt.Errorf("while checking for empty wal archive check file %q: %w", markerFilePath, err)
}
return utils.IsEmptyWalArchiveCheckEnabled(&cluster.ObjectMeta) && markerFilePresent, nil
}
// Restore implements the WALService interface // Restore implements the WALService interface
func (w WALServiceImplementation) Restore( func (w WALServiceImplementation) Restore(
ctx context.Context, ctx context.Context,
@ -249,9 +279,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 +320,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 +352,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 +378,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 +389,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 +411,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 +461,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 +569,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 {

View File

@ -20,12 +20,21 @@ SPDX-License-Identifier: Apache-2.0
package common package common
import ( import (
"context"
"os"
"path/filepath"
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"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
) )
var _ = Describe("resolveRestoreObjectStore", func() { var _ = Describe("resolveRestoreObjectStore", func() {
@ -96,3 +105,142 @@ 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())
})
})
var _ = Describe("resolveArchiveEmptyWalArchiveCheck", func() {
// skipAnnotation mirrors the unexported constant in cloudnative-pg's
// pkg/utils; hard-coding the literal makes a divergence surface as a
// failing test rather than silently disabling the check.
const skipAnnotation = "cnpg.io/skipEmptyWalArchiveCheck"
clusterWith := func(annotationValue *string) *cnpgv1.Cluster {
cluster := &cnpgv1.Cluster{}
if annotationValue != nil {
cluster.Annotations = map[string]string{skipAnnotation: *annotationValue}
}
return cluster
}
// markerPath returns the marker file path inside a fresh temp dir,
// creating the file there when present is true.
markerPath := func(present bool) string {
filePath := filepath.Join(GinkgoT().TempDir(), metadata.CheckEmptyWalArchiveFile)
if present {
Expect(os.WriteFile(filePath, []byte{}, 0o600)).To(Succeed())
}
return filePath
}
When("the operator sets the decision", func() {
It("obeys true, ignoring the annotation and the marker file", func() {
// annotation would skip the check and the marker is absent, yet the
// operator's explicit true must still win.
got, err := resolveArchiveEmptyWalArchiveCheck(
ptr.To(true), clusterWith(ptr.To("enabled")), markerPath(false))
Expect(err).NotTo(HaveOccurred())
Expect(got).To(BeTrue())
})
It("obeys false, ignoring the annotation and the marker file", func() {
// annotation would keep the check on and the marker is present, yet the
// operator's explicit false must still win.
got, err := resolveArchiveEmptyWalArchiveCheck(
ptr.To(false), clusterWith(nil), markerPath(true))
Expect(err).NotTo(HaveOccurred())
Expect(got).To(BeFalse())
})
})
When("the operator predates the field (nil decision)", func() {
DescribeTable(
"falls back to the annotation combined with the marker file",
func(annotationValue *string, markerPresent bool, expected bool) {
got, err := resolveArchiveEmptyWalArchiveCheck(
nil, clusterWith(annotationValue), markerPath(markerPresent))
Expect(err).NotTo(HaveOccurred())
Expect(got).To(Equal(expected))
},
Entry("no annotation and marker present: check runs", nil, true, true),
Entry("no annotation and marker absent: check skipped", nil, false, false),
Entry("opt-out annotation and marker present: check skipped", ptr.To("enabled"), true, false),
Entry("unrelated annotation value and marker present: check runs", ptr.To("something-else"), true, true),
Entry("empty annotation value and marker present: check runs", ptr.To(""), true, true),
)
})
})

View File

@ -113,6 +113,7 @@ func (impl JobHookImpl) Restore(
configuration.Cluster, configuration.Cluster,
&targetObjectStore.Spec.Configuration, &targetObjectStore.Spec.Configuration,
targetObjectStore.Name, targetObjectStore.Name,
req.CheckEmptyWalArchive,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -250,6 +251,7 @@ func (impl *JobHookImpl) checkBackupDestination(
cluster *cnpgv1.Cluster, cluster *cnpgv1.Cluster,
barmanConfiguration *cnpgv1.BarmanObjectStoreConfiguration, barmanConfiguration *cnpgv1.BarmanObjectStoreConfiguration,
objectStoreName string, objectStoreName string,
operatorCheckEmptyWalArchive *bool,
) error { ) error {
// Get environment from cache // Get environment from cache
env, err := barmanCredentials.EnvSetCloudCredentialsAndCertificates(ctx, env, err := barmanCredentials.EnvSetCloudCredentialsAndCertificates(ctx,
@ -288,14 +290,26 @@ func (impl *JobHookImpl) checkBackupDestination(
} }
} }
// Check if we're ok to archive in the desired destination if resolveRestoreEmptyWalArchiveCheck(operatorCheckEmptyWalArchive, cluster) {
if utils.IsEmptyWalArchiveCheckEnabled(&cluster.ObjectMeta) {
return common.CheckBackupDestination(ctx, barmanConfiguration, walArchiver, serverName) return common.CheckBackupDestination(ctx, barmanConfiguration, walArchiver, serverName)
} }
return nil return nil
} }
// resolveRestoreEmptyWalArchiveCheck reports whether the destination must be
// verified before restoring. When the operator sets the decision (non-nil) it
// is obeyed as-is; a nil value comes from an operator that predates this field,
// so we fall back to the Cluster annotation. Unlike archiving, restore is a
// one-shot operation that has never been gated on the first-archive marker
// file, so the annotation is the only fallback needed.
func resolveRestoreEmptyWalArchiveCheck(operatorDecision *bool, cluster *cnpgv1.Cluster) bool {
if operatorDecision != nil {
return *operatorDecision
}
return utils.IsEmptyWalArchiveCheckEnabled(&cluster.ObjectMeta)
}
// restoreCustomWalDir moves the current pg_wal data to the specified custom wal dir and applies the symlink // restoreCustomWalDir moves the current pg_wal data to the specified custom wal dir and applies the symlink
// returns indicating if any changes were made and any error encountered in the process // returns indicating if any changes were made and any error encountered in the process
func (impl JobHookImpl) restoreCustomWalDir(ctx context.Context) (bool, error) { func (impl JobHookImpl) restoreCustomWalDir(ctx context.Context) (bool, error) {

View File

@ -0,0 +1,66 @@
/*
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 restore
import (
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
"k8s.io/utils/ptr"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("resolveRestoreEmptyWalArchiveCheck", func() {
// skipAnnotation mirrors the unexported constant in cloudnative-pg's
// pkg/utils; hard-coding the literal makes a divergence surface as a
// failing test rather than silently disabling the check.
const skipAnnotation = "cnpg.io/skipEmptyWalArchiveCheck"
clusterWith := func(annotationValue *string) *cnpgv1.Cluster {
cluster := &cnpgv1.Cluster{}
if annotationValue != nil {
cluster.Annotations = map[string]string{skipAnnotation: *annotationValue}
}
return cluster
}
When("the operator sets the decision", func() {
It("obeys true even when the annotation would skip the check", func() {
Expect(resolveRestoreEmptyWalArchiveCheck(ptr.To(true), clusterWith(ptr.To("enabled")))).To(BeTrue())
})
It("obeys false even when the annotation would keep the check on", func() {
Expect(resolveRestoreEmptyWalArchiveCheck(ptr.To(false), clusterWith(nil))).To(BeFalse())
})
})
When("the operator predates the field (nil decision)", func() {
DescribeTable(
"falls back to the Cluster annotation, never to a marker file",
func(annotationValue *string, expected bool) {
Expect(resolveRestoreEmptyWalArchiveCheck(nil, clusterWith(annotationValue))).To(Equal(expected))
},
Entry("no annotation: check runs", nil, true),
Entry("opt-out annotation: check skipped", ptr.To("enabled"), false),
Entry("unrelated annotation value: check runs", ptr.To("something-else"), true),
Entry("empty annotation value: check runs", ptr.To(""), true),
)
})
})

View File

@ -0,0 +1,32 @@
/*
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 restore
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestRestore(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Restore job hook test suite")
}

View File

@ -72,8 +72,8 @@ func newGCSDeployment(namespace, name string) *appsv1.Deployment {
{ {
Name: name, Name: name,
// renovate: datasource=docker depName=fsouza/fake-gcs-server versioning=docker // renovate: datasource=docker depName=fsouza/fake-gcs-server versioning=docker
// Version: 1.55.0 // Version: 1.55.1
Image: "fsouza/fake-gcs-server@sha256:2845d1504bb4a5a4fe54b16dd70e398814eb139af49b01b07839e016120ff123", Image: "fsouza/fake-gcs-server@sha256:91afded49de804aa61b5f3eb6c7cd65205acf9e5c5e047cf0ba7d9507af806c8",
Ports: []corev1.ContainerPort{ Ports: []corev1.ContainerPort{
{ {
ContainerPort: 4443, ContainerPort: 4443,

View File

@ -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.1 // Version: 2.36.3
Image: "docker.io/amazon/aws-cli@sha256:406ca32d31e640a56e8d52921b40528cc64bfa59ec9cb4ee1456db6746cb7292", Image: "docker.io/amazon/aws-cli@sha256:bdd02067a00c354684086071b475955c54caa7bd88b851aac99a51326fe19652",
Command: []string{"sleep", "infinity"}, Command: []string{"sleep", "infinity"},
Env: []corev1.EnvVar{ Env: []corev1.EnvVar{
{ {

View File

@ -12,15 +12,15 @@
section-matter "^1.0.0" section-matter "^1.0.0"
strip-bom-string "^1.0.0" strip-bom-string "^1.0.0"
"@algolia/abtesting@1.21.2": "@algolia/abtesting@1.22.0":
version "1.21.2" version "1.22.0"
resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.21.2.tgz#798e51b0226b6ed303a7d891235606b674a87857" resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.22.0.tgz#7537637f52d2fe00b3714fe2d5ce8cb856be35ff"
integrity sha512-uXj0rgk30EpsKvOpuS+R+1XFDrnm56hED1Lz56e8uBkZdKCxw99LS2U8eXBqAHYU8kpkbsnV1GC8velBG070Hg== integrity sha512-BFR6zNowNKcY7Ou7TaJc9QWexES4YKPbmf/OTFofpdsdhz4x6q0lbxp3duO0EHnyrN7rE4ba/TSXuY+BDGu4+g==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/autocomplete-core@1.19.2": "@algolia/autocomplete-core@1.19.2":
version "1.19.2" version "1.19.2"
@ -62,126 +62,126 @@
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.9.tgz#c5b05e23c71027e4e45a301f286593dffdcdfbdf" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.9.tgz#c5b05e23c71027e4e45a301f286593dffdcdfbdf"
integrity sha512-YosP9Uoek6y/Ur1r1qeogk4biMe/hzkyNcgMCciw0//3XpCM7VlYLSHnyt/vOnEOGhCCc0+3v+unEiH6zz+Z1A== integrity sha512-YosP9Uoek6y/Ur1r1qeogk4biMe/hzkyNcgMCciw0//3XpCM7VlYLSHnyt/vOnEOGhCCc0+3v+unEiH6zz+Z1A==
"@algolia/client-abtesting@5.55.2": "@algolia/client-abtesting@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.55.2.tgz#5c7d1632051b05ef155a6ea7e4a9454d5c6d5a08" resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.56.0.tgz#25be0db6f97ae91dfdbaffbe9eae99e963310891"
integrity sha512-y7Epol8HcjlBxKXHhyhfFPFhm78B3P6x9cCbCyGTdxjsdVCptXCy5hpkZWxjGpnaLHvWsHS4QRF0TiBOLst2xg== integrity sha512-7r4Z3NC7yU1oAQVWJNA2HX7tX481F3pJvCGyLIXiTdBcthz4Q/o21jwcMYDFkuI92UWTNBQQmHYgwHo1zS5dzg==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/client-analytics@5.55.2": "@algolia/client-analytics@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.55.2.tgz#770694ceef05213a2dc1c64bf3cb9c0b33a16b71" resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.56.0.tgz#bcace36358cda26ca285f3a100544db0ce29aabe"
integrity sha512-8Pxj2VVmpM2d+UZufnlTq7T1QIcYPVugLV5XC50PnHsV5uRM9CSoYkg2Y+CwqwRk2La0xK5QsfZ0obIU+9XftQ== integrity sha512-avmjXQSq+jadFO8Xl2em05/uQdQnEmHsJyOAdVbZkmVgpMfxL12aJwVVfGNwYr9nulcpuJN1X0lTaQ5wxuNGcA==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/client-common@5.55.2": "@algolia/client-common@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.55.2.tgz#17347bdd5a118b7966231a73c59cac44d256071c" resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.56.0.tgz#6190221a7091dfa1a0e0a3b5964e92b1b59968ba"
integrity sha512-9L4IpIYUqA63a7sw1trnHQGUvwiAjKz67nsgDnal98JGAc7wyposRb0Iag+eiMuyzFFaSHLe2/rGyIo+PafRBA== integrity sha512-v2TPStUhY//ripPjIVclZ8AWc7DEGooXULZGFlFu37zNatgHjw34oZZ+OSbbc/YHO+xZwPl62I1k8xH1m4S2eg==
"@algolia/client-insights@5.55.2": "@algolia/client-insights@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.55.2.tgz#3e575307d01d2e6ccd7394b7428edd22ec68057c" resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.56.0.tgz#2ff179c8924ff188d4604e32aef645c709cc76be"
integrity sha512-ZBm2ytY5EHFcj+kjNsXxMNO/TGlOHe2fBFXGKHJOM1bk1rAy4o2YI+d9oV/w/jrqx44pvJMJlc8X6vKnCuDgUQ== integrity sha512-P0ehROpM4Sem3Sqo5x2cKPgj67D3G3jy0rh1Amwkcvsfr6tkvIcdCmerieanqTF7NxUMPNFLkpIFeMO8Rpa50w==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/client-personalization@5.55.2": "@algolia/client-personalization@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.55.2.tgz#1c5458095fdfdd2dd0ed8dcd5b94962db2852400" resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.56.0.tgz#64f8197c46c60306a115bc4024f6ebce2d8140d8"
integrity sha512-3FGVW/jDk7sdYwqa2NKnF/qXWcttc4bvGrwNbvqz3VoWSRv42CNvRk+3Y9QJFIUf1vY50hAuVWUoFKdyc8vaXA== integrity sha512-SXK3Vn3WVxyzbm31oePZBJkp1wpOyuWdd4B/Pv7n0aXDxmeSWhC1R1FC1517mMrFAIaPH4Rt0x6RUe7ZNjz8FA==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/client-query-suggestions@5.55.2": "@algolia/client-query-suggestions@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.55.2.tgz#7bf49bf6f7832943646dcaa1ffc2873e54bb783e" resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.56.0.tgz#e4a28bc249e9c69f0b5ef280b72a12e32e8c53c8"
integrity sha512-JsG8LovDAYul5t8e533tZ3O1uZILxso5zsTtB7ONc5RJ8ACdTxAAC/jaOnsBNYb+x+STP7fzx/Iro55v5DNgoQ== integrity sha512-5+ZdX8garFnmycnZgKhtXHePEaLj5zqDxI/0lkhhluzCcvTn0/PvvTirTg8hHYetQHvn7GDyeAiqTAieMvMW4A==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/client-search@5.55.2": "@algolia/client-search@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.55.2.tgz#8cd3d994598210e5428ca9a64dd3f17620bfbf08" resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.56.0.tgz#66b19d5382bf47a16105817b78e372f5e9039508"
integrity sha512-5wDnoIfC75zJ2MSHv5SSzTlRL2z7jQMbqQ5jrzottuq2p3oBObv8pD/JpXWu8pRaimaxNr3/Bs/KZIGVXxJ7hg== integrity sha512-+mKUdYvqOi0BcvpAEyCEw49vSBptufIcfibtHz2bdr1pI789M46Yt0uQEk/sxtK3teh71OQvVFHaTDzShUWewQ==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/events@^4.0.1": "@algolia/events@^4.0.1":
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950"
integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==
"@algolia/ingestion@1.55.2": "@algolia/ingestion@1.56.0":
version "1.55.2" version "1.56.0"
resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.55.2.tgz#e247f70c5055569af70e3c676853bad4c422ab6c" resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.56.0.tgz#1b3c41b8f1c5a2d309610683e3d1b99f962d92df"
integrity sha512-da+SC6ikpza98W7C5ChsKEQDvZc8PQLQ0sxmQ5yMRsHpdD3iPKnclJA6ViB5Nr5T9qOX+IDswC6AyqY4V3rtug== integrity sha512-9g/zj+AZx5moFcdFIrYQoVrueXivjUcc3MQHtCYT8WhIuk1lUh1AyEhvJCS0XBZld09cLvd1AZ3BvDBpVpX2UA==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/monitoring@1.55.2": "@algolia/monitoring@1.56.0":
version "1.55.2" version "1.56.0"
resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.55.2.tgz#56c8b9e5b8e64d5f8fd41a37854eb5559cb798d4" resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.56.0.tgz#11cc9198e778466eafde5a12d02fd02cfcbd1710"
integrity sha512-Y8kEcPqCiIEeaGv83l9RRA09mfYECqAJHNnOyEtZc9UirI6XBMUyFVss/sSeYUiV/Lf30hkbWcl00V1uXsf86Q== integrity sha512-Qf3Sr6f9A9uxCZUf3MXS0d2b877uYzEB5yxqpVGXAhcJnBCQjrRRon0KvefpGkxy+BshrIJs96OUoMtGqXTFDA==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/recommend@5.55.2": "@algolia/recommend@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.55.2.tgz#9549d2fe261dca9ac94c144131ea980c56a6442b" resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.56.0.tgz#6c96193cb91cf5c9f3c884fdf064e15dfe6cb742"
integrity sha512-5zmobuCQqFZkx+84Nt+suL7vo6jTh2CfAs2ndDSeTS2QHvnzP8YEEGWtWftjyACI0cK/FuH8urWwCHP+d2j8TA== integrity sha512-GXWG1rWc5wu8hY4N33Y3b6ernY6sAdAvmKWN/zHAiACOx40WnpG0TVX5YazCAr/9gOYGInSiM2A0y2jy2xbiDA==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
"@algolia/requester-browser-xhr@5.55.2": "@algolia/requester-browser-xhr@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.55.2.tgz#087322fcdfb35fdf8226d2ca966628c49f711d74" resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.56.0.tgz#b1f4705c53f1602ec14339999bfbf0e3e9a7bbc8"
integrity sha512-qnGUUuWG66dRMnr33owLsrYIh9fHVxtU4R2rd3SpneAHuoAUcGbDOWNrj05glVU6M8yOqo9gQ22K8zpz0I8Xpg== integrity sha512-7t24cBxaInS3mZb7ddEaZT/tp6q+/aR4YttsQVyP1/i+LmwPR34atO35KjaLFCcRVrlP7sYOAqkCfg6lIRB+ew==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-fetch@5.55.2": "@algolia/requester-fetch@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.55.2.tgz#a01695738861a80181f231ce7e8fca6f7a6e4072" resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.56.0.tgz#03f0aeea08efc991ab9f0663f1ea63df720fd9ba"
integrity sha512-lKZ5uhafMvR7dWCJEyuaeyZitid1I3ICx+k0vGf5x/ktdIQvc7bndCiOPpmIDqUmN26FE3jTehkAzSqee95G2Q== integrity sha512-R7ePHgVYmDFjZpvrsVAfbDz/d4RxKAYZ5/vgLfIsCVRZRryjWl/3INOxpOICzitehQ5FjNtNjcLQTrmHPTcHBQ==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/requester-node-http@5.55.2": "@algolia/requester-node-http@5.56.0":
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.55.2.tgz#5ceae3de5e223366fc5b3e643fcc0542909b87e8" resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.56.0.tgz#238bfa98ed145e261c1db7e133bee6390ba58c94"
integrity sha512-Zc90xvKWUvxcNicvvTO9Pr/hT2TAnkixOIzJm/KMj5Ptm2pKjk71ngTsdkbRtJQvhZ2Kr9N1YdIjLrNHB5P2xw== integrity sha512-PIOUXlSnrqM0S+WOgDRb4RzotydJH7ZoT6tOyL7tAO7qJOfvX5wsEW8Pe+PMKMwvuI4/gIyK9cg2H7lJXqnc4Q==
dependencies: dependencies:
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.29.7": "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.29.7":
version "7.29.7" version "7.29.7"
@ -2616,9 +2616,9 @@
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@sinclair/typebox@^0.27.8": "@sinclair/typebox@^0.27.8":
version "0.27.10" version "0.27.12"
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.10.tgz#beefe675f1853f73676aecc915b2bd2ac98c4fc6" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.12.tgz#0cacd3cff047a32936b1ace47ea7c86eaab60a7f"
integrity sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA== integrity sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==
"@sindresorhus/is@^4.6.0": "@sindresorhus/is@^4.6.0":
version "4.6.0" version "4.6.0"
@ -3400,24 +3400,24 @@ algoliasearch-helper@^3.26.0:
"@algolia/events" "^4.0.1" "@algolia/events" "^4.0.1"
algoliasearch@^5.37.0: algoliasearch@^5.37.0:
version "5.55.2" version "5.56.0"
resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.55.2.tgz#5aa9426faedfa63c6433e6ba78b1843c8208e012" resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.56.0.tgz#042f1a39dfa951356206f43dece1c8d1ea1721bd"
integrity sha512-OyacJsaeuLUvGWOynNqYc6sx88XvyoG39wMT8SYqL3l9wwaorDW/LPRbUPfhzw0bWsUWzNCZTnFYOrWFBKsUaw== integrity sha512-PrqppUmhT4ENdas2pH9caE7efUcxy6EcSFhWzosiVuQBzu2tQ5yLTI6jwomT/1cuBnivzGfxiJCqDNN9FRRh+Q==
dependencies: dependencies:
"@algolia/abtesting" "1.21.2" "@algolia/abtesting" "1.22.0"
"@algolia/client-abtesting" "5.55.2" "@algolia/client-abtesting" "5.56.0"
"@algolia/client-analytics" "5.55.2" "@algolia/client-analytics" "5.56.0"
"@algolia/client-common" "5.55.2" "@algolia/client-common" "5.56.0"
"@algolia/client-insights" "5.55.2" "@algolia/client-insights" "5.56.0"
"@algolia/client-personalization" "5.55.2" "@algolia/client-personalization" "5.56.0"
"@algolia/client-query-suggestions" "5.55.2" "@algolia/client-query-suggestions" "5.56.0"
"@algolia/client-search" "5.55.2" "@algolia/client-search" "5.56.0"
"@algolia/ingestion" "1.55.2" "@algolia/ingestion" "1.56.0"
"@algolia/monitoring" "1.55.2" "@algolia/monitoring" "1.56.0"
"@algolia/recommend" "5.55.2" "@algolia/recommend" "5.56.0"
"@algolia/requester-browser-xhr" "5.55.2" "@algolia/requester-browser-xhr" "5.56.0"
"@algolia/requester-fetch" "5.55.2" "@algolia/requester-fetch" "5.56.0"
"@algolia/requester-node-http" "5.55.2" "@algolia/requester-node-http" "5.56.0"
ansi-align@^3.0.1: ansi-align@^3.0.1:
version "3.0.1" version "3.0.1"
@ -3501,12 +3501,12 @@ astring@^1.8.0:
integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg== integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==
autoprefixer@^10.4.19, autoprefixer@^10.4.23: autoprefixer@^10.4.19, autoprefixer@^10.4.23:
version "10.5.3" version "10.5.4"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.5.3.tgz#cd6f4c611cef98055c998b5de8e6b1759f024447" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.5.4.tgz#3b7dd848b4155514a95ad1f6ce598844bea09697"
integrity sha512-bJRzflk8GgE4JX+iZNEwz9f9p460NCHnU7bd+CZ9vIjIlZuTkt6F3WSl2oNO8StZBFx17nLEsiQ6H2wcZiY7nA== integrity sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==
dependencies: dependencies:
browserslist "^4.28.6" browserslist "^4.28.6"
caniuse-lite "^1.0.30001805" caniuse-lite "^1.0.30001806"
fraction.js "^5.3.4" fraction.js "^5.3.4"
picocolors "^1.1.1" picocolors "^1.1.1"
postcss-value-parser "^4.2.0" postcss-value-parser "^4.2.0"
@ -3777,10 +3777,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2" lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0" lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001803, caniuse-lite@^1.0.30001805: caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001803, caniuse-lite@^1.0.30001806:
version "1.0.30001805" version "1.0.30001806"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001805.tgz#78d5d5968a69b7ff81af87a96d7ddc7ea6670b1e" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz#1bc8e502b723fa393455dfbedd5ccec0c29bb74e"
integrity sha512-52noaS3DubycKSXaU30TwPGIp+POyQSUVa5jBEq3vkRkY0kjyb3LQgvhU6WGyCcyXqVLWO0Cw0Q6BSdD0kUfVA== integrity sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==
ccount@^2.0.0: ccount@^2.0.0:
version "2.0.1" version "2.0.1"
@ -4573,9 +4573,9 @@ ee-first@1.1.1:
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
electron-to-chromium@^1.5.389: electron-to-chromium@^1.5.389:
version "1.5.392" version "1.5.393"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.392.tgz#31e9f9af0d8df3d1489468a4242b173605617482" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.393.tgz#aec971df2a6f4f7e51fbacb200d66cebfc7d3c17"
integrity sha512-1yQq3VQCZRwsnYc67Oc+1fge6Lwtn0hzi6zmEVkB61Zx21kTbwJAW4dFLadl5Rc1tKhG/kSpYXnfiAhu0f0a1g== integrity sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==
emoji-regex@^8.0.0: emoji-regex@^8.0.0:
version "8.0.0" version "8.0.0"
@ -4922,9 +4922,9 @@ fast-json-stable-stringify@^2.0.0:
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-uri@^3.0.1: fast-uri@^3.0.1:
version "3.1.3" version "3.1.4"
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.3.tgz#f695a40f006aba505631573a0021ddb21194ad11" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.4.tgz#3b3daf9ce68f41f956df0b505132c0cfce9ec7af"
integrity sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg== integrity sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==
fastq@^1.6.0: fastq@^1.6.0:
version "1.20.1" version "1.20.1"
@ -6893,7 +6893,7 @@ multicast-dns@^7.2.5:
dns-packet "^5.2.2" dns-packet "^5.2.2"
thunky "^1.0.2" thunky "^1.0.2"
nanoid@^3.3.12: nanoid@^3.3.16:
version "3.3.16" version "3.3.16"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.16.tgz#a04d8ec4b1f10009d2d533947aefe4293737816c" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.16.tgz#a04d8ec4b1f10009d2d533947aefe4293737816c"
integrity sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q== integrity sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==
@ -7818,11 +7818,11 @@ postcss-zindex@^6.0.2:
integrity sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg== integrity sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==
postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.33, postcss@^8.5.4: postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.33, postcss@^8.5.4:
version "8.5.19" version "8.5.20"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.19.tgz#45ad5cfde499408e20147348237551381a922037" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.20.tgz#316a139da79484ce55969fa7bb6f2f1abcc14060"
integrity sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ== integrity sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==
dependencies: dependencies:
nanoid "^3.3.12" nanoid "^3.3.16"
picocolors "^1.1.1" picocolors "^1.1.1"
source-map-js "^1.2.1" source-map-js "^1.2.1"
@ -9463,9 +9463,9 @@ write-file-atomic@^3.0.3:
typedarray-to-buffer "^3.1.5" typedarray-to-buffer "^3.1.5"
ws@^7.3.1: ws@^7.3.1:
version "7.5.12" version "7.5.13"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.12.tgz#4ca2c04966db4dcd2f9bc4d1419d23cd1e4a18db" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.13.tgz#12aa507eaca76c295c278b1aebf4698ab2c1845f"
integrity sha512-1xGnbYN3zbog9CwuNDQULNRrTCLIn46/WmpR1f0w6PsCYQHkylZr5vkd6kfMZYV6pRnQkcPNRyiA8LsrNKyhpg== integrity sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==
ws@^8.18.0: ws@^8.18.0:
version "8.21.1" version "8.21.1"