Merge pull request #8213 from brahmaroutu/pull_status_2404
Print a status message when pull command is executed
This commit is contained in:
commit
f69a262464
4 changed files with 43 additions and 11 deletions
|
@ -23,6 +23,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
# EXAMPLES
|
||||
|
||||
# Pull a repository with multiple images
|
||||
# Note that if the image is previously downloaded then the status would be
|
||||
# 'Status: Image is up to date for fedora'
|
||||
|
||||
$ sudo docker pull fedora
|
||||
Pulling repository fedora
|
||||
|
@ -31,6 +33,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
511136ea3c5a: Download complete
|
||||
73bd853d2ea5: Download complete
|
||||
|
||||
Status: Downloaded newer image for fedora
|
||||
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
fedora rawhide ad57ef8d78d7 5 days ago 359.3 MB
|
||||
|
@ -39,6 +43,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
fedora latest 105182bb5e8b 5 days ago 372.7 MB
|
||||
|
||||
# Pull an image, manually specifying path to the registry and tag
|
||||
# Note that if the image is previously downloaded then the status would be
|
||||
# 'Status: Image is up to date for registry.hub.docker.com/fedora:20'
|
||||
|
||||
$ sudo docker pull registry.hub.docker.com/fedora:20
|
||||
Pulling repository fedora
|
||||
|
@ -46,6 +52,8 @@ It is also possible to specify a non-default registry to pull from.
|
|||
511136ea3c5a: Download complete
|
||||
fd241224e9cf: Download complete
|
||||
|
||||
Status: Downloaded newer image for registry.hub.docker.com/fedora:20
|
||||
|
||||
$ sudo docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||
fedora 20 3f2fed40e4b0 4 days ago 372.7 MB
|
||||
|
|
|
@ -93,6 +93,8 @@ download the `centos` image.
|
|||
ef52fb1fe610: Download complete
|
||||
. . .
|
||||
|
||||
Status: Downloaded newer image for centos
|
||||
|
||||
We can see that each layer of the image has been pulled down and now we
|
||||
can run a container from this image and we won't have to wait to
|
||||
download the image.
|
||||
|
|
|
@ -67,6 +67,8 @@ Once you've found the image you want, you can download it with `docker pull <ima
|
|||
511136ea3c5a: Download complete
|
||||
7064731afe90: Download complete
|
||||
|
||||
Status: Downloaded newer image for centos
|
||||
|
||||
You now have an image from which you can run containers.
|
||||
|
||||
## Contributing to Docker Hub
|
||||
|
|
|
@ -122,6 +122,8 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
}
|
||||
|
||||
errors := make(chan error)
|
||||
|
||||
layers_downloaded := false
|
||||
for _, image := range repoData.ImgList {
|
||||
downloadImage := func(img *registry.ImgData) {
|
||||
if askedTag != "" && img.Tag != askedTag {
|
||||
|
@ -158,15 +160,17 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s", img.Tag, localName), nil))
|
||||
success := false
|
||||
var lastErr error
|
||||
var lastErr, err error
|
||||
var is_downloaded bool
|
||||
if mirrors != nil {
|
||||
for _, ep := range mirrors {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, mirror: %s", img.Tag, localName, ep), nil))
|
||||
if err := s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
if is_downloaded, err = s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
// Don't report errors when pulling from mirrors.
|
||||
log.Debugf("Error pulling image (%s) from %s, mirror: %s, %s", img.Tag, localName, ep, err)
|
||||
continue
|
||||
}
|
||||
layers_downloaded = layers_downloaded || is_downloaded
|
||||
success = true
|
||||
break
|
||||
}
|
||||
|
@ -174,13 +178,14 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
if !success {
|
||||
for _, ep := range repoData.Endpoints {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s, endpoint: %s", img.Tag, localName, ep), nil))
|
||||
if err := s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
if is_downloaded, err = s.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil {
|
||||
// It's not ideal that only the last error is returned, it would be better to concatenate the errors.
|
||||
// As the error is also given to the output stream the user will see the error.
|
||||
lastErr = err
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Error pulling image (%s) from %s, endpoint: %s, %s", img.Tag, localName, ep, err), nil))
|
||||
continue
|
||||
}
|
||||
layers_downloaded = layers_downloaded || is_downloaded
|
||||
success = true
|
||||
break
|
||||
}
|
||||
|
@ -227,18 +232,24 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
|||
}
|
||||
}
|
||||
|
||||
requestedTag := localName
|
||||
if len(askedTag) > 0 {
|
||||
requestedTag = localName + ":" + askedTag
|
||||
}
|
||||
WriteStatus(requestedTag, out, sf, layers_downloaded)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) error {
|
||||
func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint string, token []string, sf *utils.StreamFormatter) (bool, error) {
|
||||
history, err := r.GetRemoteHistory(imgID, endpoint, token)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling dependent layers", nil))
|
||||
// FIXME: Try to stream the images?
|
||||
// FIXME: Launch the getRemoteImage() in goroutines
|
||||
|
||||
layers_downloaded := false
|
||||
for i := len(history) - 1; i >= 0; i-- {
|
||||
id := history[i]
|
||||
|
||||
|
@ -262,15 +273,16 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
|||
imgJSON, imgSize, err = r.GetRemoteImageJSON(id, endpoint, token)
|
||||
if err != nil && j == retries {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
||||
return err
|
||||
return layers_downloaded, err
|
||||
} else if err != nil {
|
||||
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
img, err = image.NewImgJSON(imgJSON)
|
||||
layers_downloaded = true
|
||||
if err != nil && j == retries {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
||||
return fmt.Errorf("Failed to parse json: %s", err)
|
||||
return layers_downloaded, fmt.Errorf("Failed to parse json: %s", err)
|
||||
} else if err != nil {
|
||||
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
||||
continue
|
||||
|
@ -295,8 +307,9 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
|||
continue
|
||||
} else if err != nil {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
||||
return err
|
||||
return layers_downloaded, err
|
||||
}
|
||||
layers_downloaded = true
|
||||
defer layer.Close()
|
||||
|
||||
err = s.graph.Register(img, imgJSON,
|
||||
|
@ -306,14 +319,21 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
|||
continue
|
||||
} else if err != nil {
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error downloading dependent layers", nil))
|
||||
return err
|
||||
return layers_downloaded, err
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Download complete", nil))
|
||||
|
||||
}
|
||||
return nil
|
||||
return layers_downloaded, nil
|
||||
}
|
||||
|
||||
func WriteStatus(requestedTag string, out io.Writer, sf *utils.StreamFormatter, layers_downloaded bool) {
|
||||
if layers_downloaded {
|
||||
out.Write(sf.FormatStatus("", "Status: Downloaded newer image for %s", requestedTag))
|
||||
} else {
|
||||
out.Write(sf.FormatStatus("", "Status: Image is up to date for %s", requestedTag))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue