// PullDockerImage pulls an image and streams to a logger respecting terminal features func PullDockerImage(client *docker.Client, image *imagename.ImageName, auth *docker.AuthConfigurations) (*docker.Image, error) { if image.Storage == imagename.StorageS3 { s3storage := s3.New(client, os.TempDir()) if err := s3storage.Pull(image.String()); err != nil { return nil, err } } else { pipeReader, pipeWriter := io.Pipe() pullOpts := docker.PullImageOptions{ Repository: image.NameWithRegistry(), Registry: image.Registry, Tag: image.Tag, OutputStream: pipeWriter, RawJSONStream: true, } repoAuth, err := dockerclient.GetAuthForRegistry(auth, image) if err != nil { return nil, fmt.Errorf("Failed to authenticate registry %s, error: %s", image.Registry, err) } errch := make(chan error, 1) go func() { err := client.PullImage(pullOpts, repoAuth) if err := pipeWriter.Close(); err != nil { log.Errorf("Failed to close pull image stream for %s, error: %s", image, err) } errch <- err }() def := log.StandardLogger() fd, isTerminal := term.GetFdInfo(def.Out) out := def.Out if !isTerminal { out = def.Writer() } if err := jsonmessage.DisplayJSONMessagesStream(pipeReader, out, fd, isTerminal); err != nil { return nil, fmt.Errorf("Failed to process json stream for image: %s, error: %s", image, err) } if err := <-errch; err != nil { return nil, fmt.Errorf("Failed to pull image %s, error: %s", image, err) } } img, err := client.InspectImage(image.String()) if err != nil { return nil, fmt.Errorf("Failed to inspect image %s after pull, error: %s", image, err) } return img, nil }
// RegistryListTags returns the list of images instances obtained from all tags existing in the registry func RegistryListTags(image *imagename.ImageName, auth *docker.AuthConfigurations) (images []*imagename.ImageName, err error) { var ( name = image.Name registry = image.Registry ) regAuth, err := GetAuthForRegistry(auth, image) if err != nil { return nil, fmt.Errorf("Failed to get auth token for registry: %s, make sure you are properly logged in using `docker login` or have AWS credentials set in case of using ECR", image) } // XXX: AWS ECR Registry API v2 does not support listing tags // wo we just return a single image tag if it exists and no wildcards used if image.IsECR() { log.Debugf("ECR detected %s", registry) if !image.IsStrict() { return nil, fmt.Errorf("Amazon ECR does not support tags listing, therefore image wildcards are not supported, sorry: %s", image) } if exists, err := ecrImageExists(image, regAuth); err != nil { return nil, err } else if exists { log.Debugf("ECR image %s found in the registry", image) images = append(images, image) } return } if registry == "" { registry = "registry-1.docker.io" if !strings.Contains(name, "/") { name = "library/" + name } } var ( tg = tags{} url = fmt.Sprintf("https://%s/v2/%s/tags/list?page_size=9999&page=1", registry, name) ) log.Debugf("Listing image tags from the remote registry %s", url) if err := registryGet(url, regAuth, &tg); err != nil { return nil, err } log.Debugf("Got %d tags from the remote registry for image %s", len(tg.Tags), image) for _, t := range tg.Tags { candidate := imagename.New(image.NameWithRegistry(), t) if image.Contains(candidate) || image.Tag == candidate.Tag { images = append(images, candidate) } } return }