Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ensure progress tracker completes execution #100

Merged
merged 4 commits into from
Feb 9, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 16 additions & 4 deletions pkg/image/docker/daemon_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"math"
Expand All @@ -27,6 +28,10 @@ import (
"github.com/wagoodman/go-progress"
)

var (
ErrEmptyImage = errors.New("cannot provide an empty image")
)

// DaemonImageProvider is a image.Provider capable of fetching and representing a docker image from the docker daemon API.
type DaemonImageProvider struct {
imageStr string
Expand All @@ -52,6 +57,10 @@ func (p *DaemonImageProvider) trackSaveProgress() (*progress.TimedProgress, *pro

// docker image save clocks in at ~125MB/sec on my laptop... mileage may vary, of course :shrug:
mb := math.Pow(2, 20)
//"virtual size" is the total amount of disk-space used for the read-only image
//data used by the container and the writable layer.
//"size" (also provider by the inspect result) shows the amount of data (on disk)
//that is used for the writable layer of each container.
sec := float64(inspect.VirtualSize) / (mb * 125)
approxSaveTime := time.Duration(sec*1000) * time.Millisecond

Expand Down Expand Up @@ -169,6 +178,12 @@ func (p *DaemonImageProvider) Provide() (*image.Image, error) {
if err != nil {
return nil, fmt.Errorf("unable to trace image save progress: %w", err)
}
defer func() {
// NOTE: progress trackers should complete at the end of this function
// whether the function errors or succeeds.
estimateSaveProgress.SetCompleted()
copyProgress.SetComplete()
}()

stage.Current = "requesting image from docker"
readCloser, err := p.client.ImageSave(context.Background(), []string{p.imageStr})
Expand All @@ -182,9 +197,6 @@ func (p *DaemonImageProvider) Provide() (*image.Image, error) {
}
}()

// cancel indeterminate progress
estimateSaveProgress.SetCompleted()
jonasagx marked this conversation as resolved.
Show resolved Hide resolved

// save the image contents to the temp file
// note: this is the same image that will be used to querying image content during analysis
stage.Current = "saving image to disk"
Expand All @@ -193,7 +205,7 @@ func (p *DaemonImageProvider) Provide() (*image.Image, error) {
return nil, fmt.Errorf("unable to save image to tar: %w", err)
}
if nBytes == 0 {
return nil, fmt.Errorf("cannot provide an empty image")
return nil, ErrEmptyImage
jonasagx marked this conversation as resolved.
Show resolved Hide resolved
}

// use the existing tarball provider to process what was pulled from the docker daemon
Expand Down