internal/util/cmd/retry.go (29 lines of code) (raw):

package cmd import ( "context" "fmt" "os/exec" "time" "go.uber.org/zap" "github.com/aws/eks-hybrid/internal/logger" ) // Builder builds a exec.Cmd. Each invocation should return a new instance // so they can be retried independently. type Builder func(context.Context) *exec.Cmd // Retry runs the command until it succeeds or the context is cancelled. // The backoff duration is the time to wait between retries. func Retry(ctx context.Context, newCmd Builder, backoff time.Duration) error { log := logger.FromContext(ctx) var err error for { var out []byte cmd := newCmd(ctx) out, err = cmd.CombinedOutput() if err == nil { return nil } err = fmt.Errorf("running command %s: %s [Err %s]", cmd.Args, out, err) log.Info("Command failed, retrying", zap.Duration("backoff", backoff), zap.Error(err)) select { case <-ctx.Done(): return fmt.Errorf("%s: %w", ctx.Err(), err) case <-time.After(backoff): } } }