diff --git a/pkg/minikube/perf/binary.go b/pkg/minikube/perf/binary.go index f0b208b317ae..cec50bd223a1 100644 --- a/pkg/minikube/perf/binary.go +++ b/pkg/minikube/perf/binary.go @@ -54,6 +54,29 @@ func NewBinary(b string) (*Binary, error) { return newBinaryFromPR(b) } +// IsExist returns a boolean indicating binary exist in file system or GCS +func IsExist(path string) (bool, error) { + if !strings.HasPrefix(path, prPrefix) { + _, err := os.Stat(path) + return !os.IsNotExist(err), err + } + + pr, err := extractPRIDFromPath(path) + if err != nil { + return false, err + } + + ctx := context.Background() + client, err := storage.NewClient(ctx, option.WithoutAuthentication()) + if err != nil { + return false, errors.Wrap(err, "getting storage client") + } + defer client.Close() + + _, err = newObjectFromStorage(ctx, client, pr) + return err != nil, err +} + // Name returns the name of the binary func (b *Binary) Name() string { if b.pr != 0 { @@ -62,6 +85,27 @@ func (b *Binary) Name() string { return filepath.Base(b.path) } +// extractPRIDFromPath extracts PR ID as a int from path which started with prPrefix +func extractPRIDFromPath(path string) (int, error) { + pr := strings.TrimPrefix(path, prPrefix) + // try to convert to int + i, err := strconv.Atoi(pr) + if err != nil { + return -1, errors.Wrapf(err, "converting %s to an integer", pr) + } + return i, err +} + +// newObjectFromStorage return storage.ObjectHandler for minikube binary for pr +func newObjectFromStorage(ctx context.Context, client *storage.Client, pr int) (*storage.ObjectHandle, error) { + // first make sure object exists + obj := client.Bucket(bucket).Object(fmt.Sprintf("%d/minikube-%s-amd64", pr, runtime.GOOS)) + if _, err := obj.Attrs(ctx); err != nil { + return nil, fmt.Errorf("minikube binary for pr %v does not exist in bucket", pr) + } + return obj, nil +} + func (b *Binary) download() error { ctx := context.Background() client, err := storage.NewClient(ctx, option.WithoutAuthentication()) @@ -70,10 +114,9 @@ func (b *Binary) download() error { } defer client.Close() - // first make sure object exists - obj := client.Bucket(bucket).Object(fmt.Sprintf("%d/minikube-%s-amd64", b.pr, runtime.GOOS)) - if _, err := obj.Attrs(ctx); err != nil { - return fmt.Errorf("minikube binary for pr %v does not exist in bucket", b.pr) + obj, err := newObjectFromStorage(ctx, client, b.pr) + if err != nil { + return err } rc, err := obj.NewReader(ctx) @@ -98,11 +141,9 @@ func (b *Binary) download() error { // newBinaryFromPR downloads the minikube binary built for the pr by Jenkins from GCS func newBinaryFromPR(pr string) (*Binary, error) { - pr = strings.TrimPrefix(pr, prPrefix) - // try to convert to int - i, err := strconv.Atoi(pr) + i, err := extractPRIDFromPath(pr) if err != nil { - return nil, errors.Wrapf(err, "converting %s to an integer", pr) + return nil, err } b := &Binary{ diff --git a/pkg/perf/monitor/execute.go b/pkg/perf/monitor/execute.go index 543ed0114cd8..e3d3993b1cf2 100644 --- a/pkg/perf/monitor/execute.go +++ b/pkg/perf/monitor/execute.go @@ -24,8 +24,11 @@ import ( "os" "os/exec" "path/filepath" + "time" "github.com/pkg/errors" + "k8s.io/minikube/pkg/minikube/perf" + "k8s.io/minikube/pkg/util/retry" ) // RunMkcmp runs minikube built at the given pr against minikube at master @@ -39,7 +42,18 @@ func RunMkcmp(ctx context.Context, pr int) (string, error) { if _, err := runCmdInMinikube(ctx, []string{"make", mkcmpPath, minikubePath}); err != nil { return "", errors.Wrap(err, "building minikube and mkcmp at head") } - return runCmdInMinikube(ctx, []string{mkcmpPath, minikubePath, fmt.Sprintf("pr://%d", pr)}) + + prBinaryPath := fmt.Sprintf("pr://%d", pr) + + isExist := func() error { + _, err := perf.IsExist(prBinaryPath) + return err + } + if err := retry.Expo(isExist, 5*time.Second, 5*time.Minute); err != nil { + return "", err + } + + return runCmdInMinikube(ctx, []string{mkcmpPath, minikubePath, prBinaryPath}) } // runCmdInMinikube runs the cmd and return stdout