mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
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
|
# EXAMPLES
|
||||||
|
|
||||||
# Pull a repository with multiple images
|
# 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
|
$ sudo docker pull fedora
|
||||||
Pulling repository fedora
|
Pulling repository fedora
|
||||||
|
@ -31,6 +33,8 @@ It is also possible to specify a non-default registry to pull from.
|
||||||
511136ea3c5a: Download complete
|
511136ea3c5a: Download complete
|
||||||
73bd853d2ea5: Download complete
|
73bd853d2ea5: Download complete
|
||||||
|
|
||||||
|
Status: Downloaded newer image for fedora
|
||||||
|
|
||||||
$ sudo docker images
|
$ sudo docker images
|
||||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||||
fedora rawhide ad57ef8d78d7 5 days ago 359.3 MB
|
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
|
fedora latest 105182bb5e8b 5 days ago 372.7 MB
|
||||||
|
|
||||||
# Pull an image, manually specifying path to the registry and tag
|
# 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
|
$ sudo docker pull registry.hub.docker.com/fedora:20
|
||||||
Pulling repository fedora
|
Pulling repository fedora
|
||||||
|
@ -46,6 +52,8 @@ It is also possible to specify a non-default registry to pull from.
|
||||||
511136ea3c5a: Download complete
|
511136ea3c5a: Download complete
|
||||||
fd241224e9cf: Download complete
|
fd241224e9cf: Download complete
|
||||||
|
|
||||||
|
Status: Downloaded newer image for registry.hub.docker.com/fedora:20
|
||||||
|
|
||||||
$ sudo docker images
|
$ sudo docker images
|
||||||
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
|
||||||
fedora 20 3f2fed40e4b0 4 days ago 372.7 MB
|
fedora 20 3f2fed40e4b0 4 days ago 372.7 MB
|
||||||
|
|
|
@ -93,6 +93,8 @@ download the `centos` image.
|
||||||
ef52fb1fe610: Download complete
|
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
|
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
|
can run a container from this image and we won't have to wait to
|
||||||
download the image.
|
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
|
511136ea3c5a: Download complete
|
||||||
7064731afe90: Download complete
|
7064731afe90: Download complete
|
||||||
|
|
||||||
|
Status: Downloaded newer image for centos
|
||||||
|
|
||||||
You now have an image from which you can run containers.
|
You now have an image from which you can run containers.
|
||||||
|
|
||||||
## Contributing to Docker Hub
|
## Contributing to Docker Hub
|
||||||
|
|
|
@ -122,6 +122,8 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
||||||
}
|
}
|
||||||
|
|
||||||
errors := make(chan error)
|
errors := make(chan error)
|
||||||
|
|
||||||
|
layers_downloaded := false
|
||||||
for _, image := range repoData.ImgList {
|
for _, image := range repoData.ImgList {
|
||||||
downloadImage := func(img *registry.ImgData) {
|
downloadImage := func(img *registry.ImgData) {
|
||||||
if askedTag != "" && img.Tag != askedTag {
|
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))
|
out.Write(sf.FormatProgress(utils.TruncateID(img.ID), fmt.Sprintf("Pulling image (%s) from %s", img.Tag, localName), nil))
|
||||||
success := false
|
success := false
|
||||||
var lastErr error
|
var lastErr, err error
|
||||||
|
var is_downloaded bool
|
||||||
if mirrors != nil {
|
if mirrors != nil {
|
||||||
for _, ep := range mirrors {
|
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))
|
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.
|
// Don't report errors when pulling from mirrors.
|
||||||
log.Debugf("Error pulling image (%s) from %s, mirror: %s, %s", img.Tag, localName, ep, err)
|
log.Debugf("Error pulling image (%s) from %s, mirror: %s, %s", img.Tag, localName, ep, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
layers_downloaded = layers_downloaded || is_downloaded
|
||||||
success = true
|
success = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -174,13 +178,14 @@ func (s *TagStore) pullRepository(r *registry.Session, out io.Writer, localName,
|
||||||
if !success {
|
if !success {
|
||||||
for _, ep := range repoData.Endpoints {
|
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))
|
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.
|
// 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.
|
// As the error is also given to the output stream the user will see the error.
|
||||||
lastErr = err
|
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))
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
layers_downloaded = layers_downloaded || is_downloaded
|
||||||
success = true
|
success = true
|
||||||
break
|
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
|
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)
|
history, err := r.GetRemoteHistory(imgID, endpoint, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling dependent layers", nil))
|
out.Write(sf.FormatProgress(utils.TruncateID(imgID), "Pulling dependent layers", nil))
|
||||||
// FIXME: Try to stream the images?
|
// FIXME: Try to stream the images?
|
||||||
// FIXME: Launch the getRemoteImage() in goroutines
|
// FIXME: Launch the getRemoteImage() in goroutines
|
||||||
|
|
||||||
|
layers_downloaded := false
|
||||||
for i := len(history) - 1; i >= 0; i-- {
|
for i := len(history) - 1; i >= 0; i-- {
|
||||||
id := history[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)
|
imgJSON, imgSize, err = r.GetRemoteImageJSON(id, endpoint, token)
|
||||||
if err != nil && j == retries {
|
if err != nil && j == retries {
|
||||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
||||||
return err
|
return layers_downloaded, err
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
img, err = image.NewImgJSON(imgJSON)
|
img, err = image.NewImgJSON(imgJSON)
|
||||||
|
layers_downloaded = true
|
||||||
if err != nil && j == retries {
|
if err != nil && j == retries {
|
||||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
|
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 {
|
} else if err != nil {
|
||||||
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
time.Sleep(time.Duration(j) * 500 * time.Millisecond)
|
||||||
continue
|
continue
|
||||||
|
@ -295,8 +307,9 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
||||||
continue
|
continue
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", 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()
|
defer layer.Close()
|
||||||
|
|
||||||
err = s.graph.Register(img, imgJSON,
|
err = s.graph.Register(img, imgJSON,
|
||||||
|
@ -306,14 +319,21 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
|
||||||
continue
|
continue
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error downloading dependent layers", nil))
|
out.Write(sf.FormatProgress(utils.TruncateID(id), "Error downloading dependent layers", nil))
|
||||||
return err
|
return layers_downloaded, err
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.Write(sf.FormatProgress(utils.TruncateID(id), "Download complete", nil))
|
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