// CacheImages will cache images on the host
//
// The cache directory currently caches images using the imagename_tag
// For example, k8s.gcr.io/kube-addon-manager:v6.5 would be
// stored at $CACHE_DIR/k8s.gcr.io/kube-addon-manager_v6.5
544463
func CacheImages(images []string, cacheDir string) error {
	var g errgroup.Group
	for _, image := range images {
		image := image
		g.Go(func() error {
			dst := filepath.Join(cacheDir, image)
			dst = sanitizeCacheDir(dst)
			if err := CacheImage(image, dst); err != nil {
				return errors.Wrapf(err, "caching image %s", dst)
			}
			return nil
		})
	}
	if err := g.Wait(); err != nil {
		return errors.Wrap(err, "caching images")
	}
	glog.Infoln("Successfully cached all images.")
	return nil
}
961201
func (r *Spec) IsInImageCache(key string) bool {
	// This is used for cache pruning. We currently only have images, but we could
	// imagine expanding on this.
	return r.imageCache.isInCache(key)
}
276490
func cacheKeys(caches ...map[string]interface{}) map[string]bool {
	keys := make(map[string]bool)
	for _, cache := range caches {
		for key := range cache {
			keys[key] = true
		}
	}
	return keys
}
754898
func (c *Cluster) imageWithDigestString(ctx context.Context, image string, authConfig *apitypes.AuthConfig) (string, error) {
	ref, err := reference.ParseAnyReference(image)
	if err != nil {
		return "", err
	}
	namedRef, ok := ref.(reference.Named)
	if !ok {
		if _, ok := ref.(reference.Digested); ok {
			return image, nil
		}
		return "", errors.Errorf("unknown image reference format: %s", image)
	}
	// only query registry if not a canonical reference (i.e. with digest)
	if _, ok := namedRef.(reference.Canonical); !ok {
		namedRef = reference.TagNameOnly(namedRef)

		taggedRef, ok := namedRef.(reference.NamedTagged)
		if !ok {
			return "", errors.Errorf("image reference not tagged: %s", image)
		}

		repo, _, err := c.config.ImageBackend.GetRepository(ctx, taggedRef, authConfig)
		if err != nil {
			return "", err
		}
		dscrptr, err := repo.Tags(ctx).Get(ctx, taggedRef.Tag())
		if err != nil {
			return "", err
		}

		namedDigestedRef, err := reference.WithDigest(taggedRef, dscrptr.Digest)
		if err != nil {
			return "", err
		}
		// return familiar form until interface updated to return type
		return reference.FamiliarString(namedDigestedRef), nil
	}
	// reference already contains a digest, so just return it
	return reference.FamiliarString(ref), nil
}
89068
func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
	if _, err := reference.ParseAnyReference(source); err != nil {
		return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", source)
	}

	ref, err := reference.ParseNormalizedNamed(target)
	if err != nil {
		return errors.Wrapf(err, "Error parsing reference: %q is not a valid repository/tag", target)
	}

	if _, isCanonical := ref.(reference.Canonical); isCanonical {
		return errors.New("refusing to create a tag with a digest reference")
	}

	ref = reference.TagNameOnly(ref)

	query := url.Values{}
	query.Set("repo", reference.FamiliarName(ref))
	if tagged, ok := ref.(reference.Tagged); ok {
		query.Set("tag", tagged.Tag())
	}

	resp, err := cli.post(ctx, "/images/"+source+"/tag", query, nil, nil)
	ensureReaderClosed(resp)
	return err
}
296759
func (f *Facade) GetRegistryImages(ctx datastore.Context) ([]registry.Image, error) {
	defer ctx.Metrics().Stop(ctx.Metrics().Start("Facade.GetRegistryImages"))
	rImages, err := f.registryStore.GetImages(ctx)
	if err != nil {
		return nil, err
	}
	return rImages, nil
}
258994
func ImageTag(conf *yaml.Config) error {
	for _, image := range conf.Pipeline {
		if !strings.Contains(image.Image, ":") {
			image.Image = image.Image + ":latest"
		}
	}
	for _, image := range conf.Services {
		if !strings.Contains(image.Image, ":") {
			image.Image = image.Image + ":latest"
		}
	}
	return nil
}
254980
func CacheTagHandler(ctx *tagContext) error {
	if !ctx.hasCacheTag {
		ctx.hasCacheTag = true
	}
	return nil
}
312994
func (c *Calcium) CacheImage(ctx context.Context, podname, nodename string, images []string, step int) (chan *types.CacheImageMessage, error) {
	ch := make(chan *types.CacheImageMessage)

	var err error
	nodes := []*types.Node{}
	if nodename != "" {
		n, err := c.GetNode(ctx, podname, nodename)
		if err != nil {
			return ch, err
		}
		nodes = append(nodes, n)
	} else {
		nodes, err = c.store.GetNodesByPod(ctx, podname)
		if err != nil {
			return ch, err
		}
	}

	if len(nodes) == 0 {
		return nil, types.ErrPodNoNodes
	}

	go func() {
		defer close(ch)
		wg := sync.WaitGroup{}
		defer wg.Wait()
		for i, node := range nodes {
			wg.Add(1)
			go func(node *types.Node) {
				defer wg.Done()
				for _, image := range images {
					m := &types.CacheImageMessage{
						Image:    image,
						Success:  true,
						Nodename: node.Name,
						Message:  "",
					}
					if err := pullImage(ctx, node, image); err != nil {
						m.Success = false
						m.Message = err.Error()
					}
					ch <- m
				}
			}(node)
			if (i+1)%step == 0 {
				log.Info("[CacheImage] Wait for puller cleaner done")
				wg.Wait()
			}
		}
	}()

	return ch, nil
}
551878
func (c *Client) SearchImages(term string) ([]APIImageSearch, error) {
	resp, err := c.do("GET", "/images/search?term="+term, doOptions{})
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	var searchResult []APIImageSearch
	if err := json.NewDecoder(resp.Body).Decode(&searchResult); err != nil {
		return nil, err
	}
	return searchResult, nil
}
310483
func addImageStreamLayersFromCache(isl *imageapi.ImageStreamLayers, is *imageapi.ImageStream, index ImageLayerIndex) []string {
	var missing []string
	for _, status := range is.Status.Tags {
		for _, item := range status.Items {
			if len(item.Image) == 0 {
				continue
			}

			obj, _, _ := index.GetByKey(item.Image)
			entry, ok := obj.(*ImageLayers)
			if !ok {
				if _, ok := isl.Images[item.Image]; !ok {
					isl.Images[item.Image] = imageapi.ImageBlobReferences{ImageMissing: true}
				}
				missing = append(missing, item.Image)
				continue
			}

			// we have already added this image once
			if _, ok := isl.Images[item.Image]; ok {
				continue
			}

			var reference imageapi.ImageBlobReferences
			for _, layer := range entry.Layers {
				reference.Layers = append(reference.Layers, layer.Name)
				if _, ok := isl.Blobs[layer.Name]; !ok {
					isl.Blobs[layer.Name] = imageapi.ImageLayerData{LayerSize: &layer.LayerSize, MediaType: layer.MediaType}
				}
			}

			if blob := entry.Config; blob != nil {
				reference.Config = &blob.Name
				if _, ok := isl.Blobs[blob.Name]; !ok {
					if blob.LayerSize == 0 {
						// only send media type since we don't the size of the manifest
						isl.Blobs[blob.Name] = imageapi.ImageLayerData{MediaType: blob.MediaType}
					} else {
						isl.Blobs[blob.Name] = imageapi.ImageLayerData{LayerSize: &blob.LayerSize, MediaType: blob.MediaType}
					}
				}
			}

			// the image manifest is always a blob - schema2 images also have a config blob referenced from the manifest
			if _, ok := isl.Blobs[item.Image]; !ok {
				isl.Blobs[item.Image] = imageapi.ImageLayerData{MediaType: entry.MediaType}
			}
			isl.Images[item.Image] = reference
		}
	}
	return missing
}
351074
func (c *connection) ImageTags(namespace, name string) (map[string]string, error) {
	if len(namespace) == 0 && reference.IsRegistryDockerHub(c.url.Host) {
		namespace = "library"
	}
	if len(name) == 0 {
		return nil, fmt.Errorf("image name must be specified")
	}

	repo, err := c.getCachedRepository(fmt.Sprintf("%s/%s", namespace, name))
	if err != nil {
		return nil, err
	}

	return repo.getTags(c)
}
179972
func (k KubeYAML) Image(in []byte, ns, kind, name, container, image string) ([]byte, error) {
	args := []string{"image", "--namespace", ns, "--kind", kind, "--name", name}
	args = append(args, "--container", container, "--image", image)
	return execKubeyaml(in, args)
}
1320438
func SortImages(images []image.Info, pattern policy.Pattern) SortedImageInfos {
	return sortImages(images, pattern)
}
7028
func (s *imageStorage) ListImages(filter ImageFilter) ([]*Metadata, error) {
	metadataDocs, err := s.listImageMetadataDocs(s.modelUUID, filter.Kind, filter.Series, filter.Arch)
	if err != nil {
		return nil, errors.Annotate(err, "cannot list image metadata")
	}
	result := make([]*Metadata, len(metadataDocs))
	for i, metadataDoc := range metadataDocs {
		result[i] = &Metadata{
			ModelUUID: s.modelUUID,
			Kind:      metadataDoc.Kind,
			Series:    metadataDoc.Series,
			Arch:      metadataDoc.Arch,
			Size:      metadataDoc.Size,
			SHA256:    metadataDoc.SHA256,
			Created:   metadataDoc.Created,
			SourceURL: metadataDoc.SourceURL,
		}
	}
	return result, nil
}
409986
func (e *hookExecutor) tagImages(hook *appsv1.LifecycleHook, rc *corev1.ReplicationController, suffix, label string) error {
	var errs []error
	for _, action := range hook.TagImages {
		value, ok := findContainerImage(rc, action.ContainerName)
		if !ok {
			errs = append(errs, fmt.Errorf("unable to find image for container %q, container could not be found", action.ContainerName))
			continue
		}
		namespace := action.To.Namespace
		if len(namespace) == 0 {
			namespace = rc.Namespace
		}
		if _, err := e.tags.ImageStreamTags(namespace).Update(&imageapiv1.ImageStreamTag{
			ObjectMeta: metav1.ObjectMeta{
				Name:      action.To.Name,
				Namespace: namespace,
			},
			Tag: &imageapiv1.TagReference{
				From: &corev1.ObjectReference{
					Kind: "DockerImage",
					Name: value,
				},
			},
		}); err != nil {
			errs = append(errs, err)
			continue
		}
		fmt.Fprintf(e.out, "--> %s: Tagged %q into %s/%s\n", label, value, action.To.Namespace, action.To.Name)
	}

	return utilerrors.NewAggregate(errs)
}
59294
func sanitizeCacheDir(image string) string {
	if runtime.GOOS == "windows" && hasWindowsDriveLetter(image) {
		// not sanitize Windows drive letter.
		return image[:2] + strings.Replace(image[2:], ":", "_", -1)
	}
	return strings.Replace(image, ":", "_", -1)
}