Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ go 1.25.0

require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
github.com/evanphx/json-patch v5.9.11+incompatible
github.com/gogo/protobuf v1.3.2
github.com/json-iterator/go v1.1.12
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9
github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs=
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down
10 changes: 4 additions & 6 deletions pkg/restic/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package restic

import (
"bytes"
"encoding/json"
"errors"
"fmt"
Expand All @@ -30,7 +31,6 @@ import (

"stash.appscode.dev/apimachinery/apis/stash/v1alpha1"

"github.com/armon/circbuf"
"k8s.io/klog/v2"
storage "kmodules.xyz/objectstore-api/api/v1"
)
Expand Down Expand Up @@ -464,11 +464,9 @@ func (w *ResticWrapper) appendCaCertFlag(args []any) []any {

func (w *ResticWrapper) run(commands ...Command) ([]byte, error) {
// write std errors into os.Stderr and buffer
errBuff, err := circbuf.NewBuffer(256)
if err != nil {
return nil, err
}
w.sh.Stderr = io.MultiWriter(os.Stderr, errBuff)
var err error
var errBuff bytes.Buffer
w.sh.Stderr = io.MultiWriter(os.Stderr, &errBuff)

for _, cmd := range commands {
if cmd.Name == ResticCMD {
Expand Down
16 changes: 7 additions & 9 deletions pkg/restic/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ func NewRetryConfig() *RetryConfig {
return false
}
combined := strings.ToLower(err.Error() + " " + output)
klog.Infoln("Combined output: " + combined)
for _, pattern := range retryablePatterns {
if strings.Contains(combined, strings.ToLower(pattern)) {
return true
Expand All @@ -64,32 +63,31 @@ func NewRetryConfig() *RetryConfig {
func (rc *RetryConfig) RunWithRetry(ctx context.Context, execFunc func() ([]byte, error)) ([]byte, error) {
var output []byte
var lastErr error
attempts := 0
attempts := 1

err := wait.PollUntilContextCancel(
ctx,
rc.Delay,
true, // Run immediately on first call
func(ctx context.Context) (bool, error) {
// Stop if max retries reached
if attempts >= rc.MaxRetries {
if attempts > rc.MaxRetries {
return false, fmt.Errorf("max retries reached")
}
output, lastErr = execFunc()
klog.Infof("Attempt #%d: retrying in %v", attempts, rc.Delay)
klog.Infof("Attempt #%d error: %v", attempts, lastErr)
klog.Infof("Attempt #%d output: %s", attempts, string(output))

if !rc.ShouldRetry(lastErr, string(output)) {
return true, nil
Comment on lines +78 to 83
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Info-level logs are misleading and potentially very noisy: "retrying in %v" is logged even when ShouldRetry returns false (i.e., when no retry will happen), and logging full output/error every attempt can leak sensitive data and produce very large logs.

Consider logging only inside the retry path, using a higher verbosity (e.g., klog.V(...)), and truncating/redacting command output before logging.

Copilot uses AI. Check for mistakes.
}
klog.Infoln("Retrying command after error",
"attempt", attempts,
"maxRetries", rc.MaxRetries,
"error", fmt.Sprintf("%s %s", lastErr, string(output)))
attempts++
return false, nil
Comment on lines +66 to 86
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attempts accounting is off-by-one: starting at 1 and incrementing only when retrying means you can hit the attempts > rc.MaxRetries guard after incrementing, without actually executing that last "attempt". This can over-report the number of attempts in the final error message and effectively reduces/changes the intended semantics of MaxRetries.

Consider incrementing the counter only when execFunc() is called (or starting from 0 and using >=), and ensuring the reported attempt count matches the number of executions.

Copilot uses AI. Check for mistakes.
},
)
if err != nil {
return nil, fmt.Errorf("failed after %d attempts: %w", attempts, lastErr)
return output, fmt.Errorf("failed after %d attempts: %w", attempts, lastErr)
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When polling ends with a non-nil err (context cancellation, poll internal error, or the "max retries reached" error), the returned error wraps lastErr instead of err. This can drop the real termination reason (e.g., context deadline exceeded) and can even wrap nil if no attempt was executed.

Consider returning/wrapping err (and optionally attaching lastErr as context) so callers can reliably detect cancellation vs command failure.

Suggested change
return output, fmt.Errorf("failed after %d attempts: %w", attempts, lastErr)
if lastErr != nil {
return output, fmt.Errorf("failed after %d attempts: %w (last error: %v)", attempts, err, lastErr)
}
return output, fmt.Errorf("failed after %d attempts: %w", attempts, err)

Copilot uses AI. Check for mistakes.
}

return output, lastErr
}
22 changes: 0 additions & 22 deletions vendor/github.com/armon/circbuf/.gitignore

This file was deleted.

20 changes: 0 additions & 20 deletions vendor/github.com/armon/circbuf/LICENSE

This file was deleted.

28 changes: 0 additions & 28 deletions vendor/github.com/armon/circbuf/README.md

This file was deleted.

92 changes: 0 additions & 92 deletions vendor/github.com/armon/circbuf/circbuf.go

This file was deleted.

3 changes: 0 additions & 3 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ github.com/PuerkitoBio/purell
# github.com/antlr4-go/antlr/v4 v4.13.0
## explicit; go 1.20
github.com/antlr4-go/antlr/v4
# github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
## explicit
github.com/armon/circbuf
# github.com/beorn7/perks v1.0.1
## explicit; go 1.11
github.com/beorn7/perks/quantile
Expand Down
Loading