Compare commits

..

4 Commits

Author SHA1 Message Date
Armando Ruocco
4c2ec2f7c4
Merge 16bc55f67e into 3cc6a882c8 2026-07-01 08:34:08 +08:00
Niccolò Fei
16bc55f67e test: remove redundant primary/standby picking logic
If pod-1 is not the primary we'd fail anyway because a timeline
bump would make all assertions about the walLogDir fail.
Also there's no reason why there should have been a switchover,
so we should not hide a failure if that happens.

Signed-off-by: Niccolò Fei <niccolo.fei@enterprisedb.com>
2026-06-26 10:15:23 +08:00
Niccolò Fei
1b383e0e20 chore: bump aws-cli to 2.35.11
Signed-off-by: Niccolò Fei <niccolo.fei@enterprisedb.com>
2026-06-26 10:15:23 +08:00
Armando Ruocco
e4d375c4a5 test(e2e): cover parallel WAL restore via the plugin
Recreate the parallel WAL-restore coverage in the plugin repo: a 2-instance
cluster archiving to minio with wal.maxParallel=3, forged WAL segments on the
object store, and assertions on the plugin's prefetch/spool/end-of-wal-stream
state machine driven through `/controller/manager wal-restore` on the standby.

Part of cloudnative-pg/cloudnative-pg#10954.

Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
2026-06-26 10:15:23 +08:00
4 changed files with 13 additions and 19 deletions

View File

@ -403,9 +403,8 @@ func reconcilePodSpec(
envs = append(envs, config.env...) envs = append(envs, config.env...)
baseProbe := &corev1.Probe{ baseProbe := &corev1.Probe{
PeriodSeconds: 1, FailureThreshold: 10,
FailureThreshold: 30, TimeoutSeconds: 10,
TimeoutSeconds: 5,
ProbeHandler: corev1.ProbeHandler{ ProbeHandler: corev1.ProbeHandler{
Exec: &corev1.ExecAction{ Exec: &corev1.ExecAction{
Command: []string{"/manager", "healthcheck", "unix"}, Command: []string{"/manager", "healthcheck", "unix"},

View File

@ -12,14 +12,14 @@
rebaseWhen: 'never', rebaseWhen: 'never',
prConcurrentLimit: 5, prConcurrentLimit: 5,
// Override default ignorePaths to scan test/e2e for emulator image dependencies // Override default ignorePaths to scan test/e2e for emulator image dependencies
// Removed: '**/test/**', '**/tests/**' (this repo's e2e Ginkgo packages live // Removed: '**/test/**'
// under test/e2e/internal/tests/**, which the plural pattern was excluding)
ignorePaths: [ ignorePaths: [
'**/node_modules/**', '**/node_modules/**',
'**/bower_components/**', '**/bower_components/**',
'**/vendor/**', '**/vendor/**',
'**/examples/**', '**/examples/**',
'**/__tests__/**', '**/__tests__/**',
'**/tests/**',
'**/__fixtures__/**', '**/__fixtures__/**',
], ],
lockFileMaintenance: { lockFileMaintenance: {

View File

@ -121,8 +121,7 @@ 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.35.11 Image: "docker.io/amazon/aws-cli:2.35.11",
Image: "docker.io/amazon/aws-cli@sha256:749bfaf91d690b9a1768083822d620f96c19defdf9ca2dc227eb3695281fda5b",
Command: []string{"sleep", "infinity"}, Command: []string{"sleep", "infinity"},
Env: []corev1.EnvVar{ Env: []corev1.EnvVar{
{ {

View File

@ -21,7 +21,6 @@ package walrestore
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -31,7 +30,6 @@ import (
apitypes "k8s.io/apimachinery/pkg/types" apitypes "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
executil "k8s.io/client-go/util/exec"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
internalClient "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/client" internalClient "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/client"
@ -69,8 +67,9 @@ const (
) )
// walFile returns the name of the n-th forged WAL segment (segment 0xF0+n on // walFile returns the name of the n-th forged WAL segment (segment 0xF0+n on
// timeline 1, log 0, for n <= 15). The high segment number keeps it out of the // timeline 1, log 0). The high segment number keeps it out of the range an idle
// range an idle PostgreSQL would archive on its own. // PostgreSQL would archive on its own. Hex formatting keeps the name a valid
// 24-character segment for any small n.
func walFile(n int) string { func walFile(n int) string {
return fmt.Sprintf("0000000100000000%08X", 0xF0+n) return fmt.Sprintf("0000000100000000%08X", 0xF0+n)
} }
@ -200,8 +199,8 @@ var _ = Describe("Parallel WAL restore", func() {
"sh", "-c", "rm -f "+spoolDirectory+"/* 2>/dev/null; true") "sh", "-c", "rm -f "+spoolDirectory+"/* 2>/dev/null; true")
} }
forge := func(src, dst string) { forge := func(src, dst string) {
// ExecuteInContainer drops stdout/stderr on a non-zero exit, so on // ExecuteInContainer folds a non-zero exit (and its output) into the
// failure this only reports the exit code, not the aws CLI's error text. // returned error, so we surface that rather than the empty stderr.
_, _, err := execInPod(ctx, clientSet, cfg, ns, s3Client, s3ClientName, _, _, err := execInPod(ctx, clientSet, cfg, ns, s3Client, s3ClientName,
"aws", "s3", "cp", walObjectURI(src), walObjectURI(dst)) "aws", "s3", "cp", walObjectURI(src), walObjectURI(dst))
Expect(err).NotTo(HaveOccurred(), "forging %s -> %s", src, dst) Expect(err).NotTo(HaveOccurred(), "forging %s -> %s", src, dst)
@ -212,6 +211,7 @@ var _ = Describe("Parallel WAL restore", func() {
return err == nil && strings.TrimSpace(out) != "" return err == nil && strings.TrimSpace(out) != ""
} }
var latestWAL string
By("archiving a real WAL on the primary and learning its name") By("archiving a real WAL on the primary and learning its name")
_, _, err := execInPod(ctx, clientSet, cfg, ns, primary, postgresContainer, _, _, err := execInPod(ctx, clientSet, cfg, ns, primary, postgresContainer,
"psql", "-tAc", "CHECKPOINT") "psql", "-tAc", "CHECKPOINT")
@ -219,7 +219,7 @@ var _ = Describe("Parallel WAL restore", func() {
out, _, err := execInPod(ctx, clientSet, cfg, ns, primary, postgresContainer, out, _, err := execInPod(ctx, clientSet, cfg, ns, primary, postgresContainer,
"psql", "-tAc", "SELECT pg_walfile_name(pg_switch_wal())") "psql", "-tAc", "SELECT pg_walfile_name(pg_switch_wal())")
Expect(err).NotTo(HaveOccurred(), "switching WAL on the primary failed") Expect(err).NotTo(HaveOccurred(), "switching WAL on the primary failed")
latestWAL := strings.TrimSpace(out) latestWAL = strings.TrimSpace(out)
Expect(latestWAL).To(HavePrefix(walLogDir), Expect(latestWAL).To(HavePrefix(walLogDir),
"the freshly bootstrapped cluster should still be on the first WAL log") "the freshly bootstrapped cluster should still be on the first WAL log")
@ -288,11 +288,7 @@ var _ = Describe("Parallel WAL restore", func() {
// #6 (first): flag is set, so the request fails fast (exit 1) and the // #6 (first): flag is set, so the request fails fast (exit 1) and the
// flag is consumed, leaving an empty spool. // flag is consumed, leaving an empty spool.
By("requesting WAL #6: fails fast on the end-of-wal-stream flag, spool cleared") By("requesting WAL #6: fails fast on the end-of-wal-stream flag, spool cleared")
restoreErr := restore(walFile(6)) Expect(restore(walFile(6))).To(HaveOccurred(), "exit code should be 1")
var exitErr executil.CodeExitError
Expect(errors.As(restoreErr, &exitErr)).To(BeTrue(),
"expected a CodeExitError, got %T: %v", restoreErr, restoreErr)
Expect(exitErr.ExitStatus()).To(Equal(1), "exit code should be 1")
Eventually(func(g Gomega) { Eventually(func(g Gomega) {
g.Expect(existsIn(pgWalPath, walFile(6))).To(BeFalse(), "#6 not restored") g.Expect(existsIn(pgWalPath, walFile(6))).To(BeFalse(), "#6 not restored")
g.Expect(spoolSegments()).To(Equal(0), "no WAL segments in spool") g.Expect(spoolSegments()).To(Equal(0), "no WAL segments in spool")