// ListImageTags returns the list of images instances obtained from all tags existing in the registry func (c *DockerClient) ListImageTags(name string) (images []*imagename.ImageName, err error) { img := imagename.NewFromString(name) if img.Storage == imagename.StorageS3 { return c.s3storage.ListTags(name) } return dockerclient.RegistryListTags(imagename.NewFromString(name), c.auth) }
// resolveVersions walks through the list of images and resolves their tags in case they are not strict func (client *DockerClient) resolveVersions(local, hub bool, vars template.Vars, containers []*Container) (err error) { // Provide function getter of all images to fetch only once var available []*imagename.ImageName getImages := func() ([]*imagename.ImageName, error) { if available == nil { available = []*imagename.ImageName{} if !local { return available, nil } // retrieving images currently available in docker var dockerImages []docker.APIImages if dockerImages, err = client.Docker.ListImages(docker.ListImagesOptions{}); err != nil { return nil, err } for _, image := range dockerImages { for _, repoTag := range image.RepoTags { available = append(available, imagename.NewFromString(repoTag)) } } } return available, nil } resolved := map[string]*imagename.ImageName{} // check images for each container for _, container := range containers { // error in configuration, fail fast if container.Image == nil { err = fmt.Errorf("Image is not specified for the container: %s", container.Name) return } // Version specified in variables var k string k = fmt.Sprintf("v_image_%s", container.Image.NameWithRegistry()) if tag, ok := vars[k]; ok { log.Infof("Resolve %s --> %s (derived by variable %s)", container.Image, tag, k) container.Image.SetTag(tag.(string)) } k = fmt.Sprintf("v_container_%s", container.Name.Name) if tag, ok := vars[k]; ok { log.Infof("Resolve %s --> %s (derived by variable %s)", container.Image, tag, k) container.Image.SetTag(tag.(string)) } // Do not resolve anything if the image is strict, e.g. "redis:2.8.11" or "redis:latest" if container.Image.IsStrict() { continue } // already resolved it for other container if _, ok := resolved[container.Image.String()]; ok { container.Image = resolved[container.Image.String()] continue } // Override to not change the common images slice var images []*imagename.ImageName if images, err = getImages(); err != nil { return err } // looking locally first candidate := container.Image.ResolveVersion(images, true) // in case we want to include external images as well, pulling list of available // images from repository or central docker hub if hub || candidate == nil { log.Debugf("Getting list of tags for %s from the registry", container.Image) var remote []*imagename.ImageName if container.Image.Storage == imagename.StorageS3 { s3storage := s3.New(client.Docker, os.TempDir()) remote, err = s3storage.ListTags(container.Image.String()) } else { remote, err = dockerclient.RegistryListTags(container.Image, client.Auth) } if err != nil { return fmt.Errorf("Failed to list tags of image %s for container %s from the remote registry, error: %s", container.Image, container.Name, err) } log.Debugf("remote: %v", remote) // Re-Resolve having hub tags candidate = container.Image.ResolveVersion(append(images, remote...), false) } if candidate == nil { err = fmt.Errorf("Image not found: %s", container.Image) return } candidate.IsOldS3Name = container.Image.IsOldS3Name log.Infof("Resolve %s --> %s", container.Image, candidate.GetTag()) container.Image = candidate resolved[container.Image.String()] = candidate } return }