feat: return proper gRPC error codes for expected conditions (#549)

The plugin now returns a 404 status code when a requested WAL file does
not exist in the object store.

This prevents misleading log entries such as "Error while handling gRPC
request" for expected missing-file scenarios.

The `ErrEndOfWALStreamReached` now returns `OutOfRange` error.

The `ErrMissingPermissions` now returns `FailedPrecondition` error.

Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Co-authored-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Co-authored-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
This commit is contained in:
Leonardo Cecchi 2025-09-25 10:36:48 +02:00 committed by GitHub
parent 65a0d11ec8
commit 08c3f1c232
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 25 deletions

View File

@ -1,16 +1,25 @@
package common
// walNotFoundError is raised when a WAL file has not been found in the object store
type walNotFoundError struct{}
import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func newWALNotFoundError() *walNotFoundError { return &walNotFoundError{} }
// ErrEndOfWALStreamReached is returned when end of WAL is detected in the cloud archive.
var ErrEndOfWALStreamReached = status.Errorf(codes.OutOfRange, "end of WAL reached")
// ShouldPrintStackTrace tells whether the sidecar log stream should contain the stack trace
func (e walNotFoundError) ShouldPrintStackTrace() bool {
return false
}
// Error implements the error interface
func (e walNotFoundError) Error() string {
return "WAL file not found"
// ErrMissingPermissions is raised when the sidecar has no
// permission to download the credentials needed to reach
// the object storage.
// This will be fixed by the reconciliation loop in the
// operator plugin.
var ErrMissingPermissions = status.Errorf(codes.FailedPrecondition,
"no permission to download the backup credentials, retrying")
// newWALNotFoundError returns a error that states that a
// certain WAL file has not been found. This error is
// compatible with GRPC status codes, resulting in a 404
// being used as a response code.
func newWALNotFoundError(walName string) error {
return status.Errorf(codes.NotFound, "wal %q not found", walName)
}

View File

@ -27,13 +27,6 @@ import (
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
)
// ErrMissingPermissions is raised when the sidecar has no
// permission to download the credentials needed to reach
// the object storage.
// This will be fixed by the reconciliation loop in the
// operator plugin.
var ErrMissingPermissions = fmt.Errorf("no permission to download the backup credentials, retrying")
// SpoolManagementError is raised when a spool management
// error has been detected
type SpoolManagementError struct {
@ -95,11 +88,14 @@ func (w WALServiceImplementation) Archive(
ctx context.Context,
request *wal.WALArchiveRequest,
) (*wal.WALArchiveResult, error) {
contextLogger := log.FromContext(ctx)
contextLogger.Debug("starting wal archive")
baseWalName := path.Base(request.GetSourceFileName())
contextLogger := log.FromContext(ctx)
contextLogger.Debug("wal archive start", "walName", baseWalName)
defer func() {
contextLogger.Debug("wal archive end", "walName", baseWalName)
}()
// Step 1: parse the configuration and get the environment variables needed
// for barman-cloud-wal-archive
configuration, err := config.NewFromClusterJSON(request.ClusterDefinition)
@ -122,6 +118,7 @@ func (w WALServiceImplementation) Archive(
)
if err != nil {
if apierrors.IsForbidden(err) {
contextLogger.Info(ErrMissingPermissions.Error())
return nil, ErrMissingPermissions
}
return nil, err
@ -350,7 +347,7 @@ func (w WALServiceImplementation) restoreFromBarmanObjectStore(
// The failure has already been logged in walRestorer.RestoreList method
if walStatus[0].Err != nil {
if errors.Is(walStatus[0].Err, barmanRestorer.ErrWALNotFound) {
return newWALNotFoundError()
return newWALNotFoundError(walStatus[0].WalName)
}
return walStatus[0].Err
@ -457,9 +454,6 @@ func gatherWALFilesToRestore(walName string, parallel int) (walList []string, er
return walList, err
}
// ErrEndOfWALStreamReached is returned when end of WAL is detected in the cloud archive.
var ErrEndOfWALStreamReached = errors.New("end of WAL reached")
// checkEndOfWALStreamFlag returns ErrEndOfWALStreamReached if the flag is set in the restorer.
func checkEndOfWALStreamFlag(walRestorer *barmanRestorer.WALRestorer) error {
contain, err := walRestorer.IsEndOfWALStream()