// layerIsPrunable returns true if the layer is not referenced by any images. func layerIsPrunable(g graph.Graph, layerNode *imagegraph.ImageLayerNode) bool { for _, predecessor := range g.To(layerNode) { glog.V(4).Infof("Examining layer predecessor %#v", predecessor) if g.Kind(predecessor) == imagegraph.ImageNodeKind { glog.V(4).Infof("Layer has an image predecessor") return false } } return true }
// streamReferencingImageComponent returns a list of ImageStreamNodes that reference a // given ImageComponentNode. func streamsReferencingImageComponent(g graph.Graph, cn *imagegraph.ImageComponentNode) []*imagegraph.ImageStreamNode { ret := []*imagegraph.ImageStreamNode{} for _, predecessor := range g.To(cn) { if g.Kind(predecessor) != imagegraph.ImageStreamNodeKind { continue } ret = append(ret, predecessor.(*imagegraph.ImageStreamNode)) } return ret }
// imageComponentIsPrunable returns true if the image component is not referenced by any images. func imageComponentIsPrunable(g graph.Graph, cn *imagegraph.ImageComponentNode) bool { for _, predecessor := range g.To(cn) { glog.V(4).Infof("Examining predecessor %#v of image config %v", predecessor, cn) if g.Kind(predecessor) == imagegraph.ImageNodeKind { glog.V(4).Infof("Config %v has an image predecessor", cn) return false } } return true }
// streamLayerReferences returns a list of ImageStreamNodes that reference a // given ImageLayerNode. func streamLayerReferences(g graph.Graph, layerNode *imagegraph.ImageLayerNode) []*imagegraph.ImageStreamNode { ret := []*imagegraph.ImageStreamNode{} for _, predecessor := range g.To(layerNode) { if g.Kind(predecessor) != imagegraph.ImageStreamNodeKind { continue } ret = append(ret, predecessor.(*imagegraph.ImageStreamNode)) } return ret }
// pruneStreams removes references from all image streams' status.tags entries // to prunable images, invoking streamPruner.PruneImageStream for each updated // stream. func pruneStreams(g graph.Graph, imageNodes []*imagegraph.ImageNode, streamPruner ImageStreamPruner) []error { errs := []error{} glog.V(4).Infof("Removing pruned image references from streams") for _, imageNode := range imageNodes { for _, n := range g.To(imageNode) { streamNode, ok := n.(*imagegraph.ImageStreamNode) if !ok { continue } stream := streamNode.ImageStream updatedTags := sets.NewString() glog.V(4).Infof("Checking if ImageStream %s/%s has references to image %s in status.tags", stream.Namespace, stream.Name, imageNode.Image.Name) for tag, history := range stream.Status.Tags { glog.V(4).Infof("Checking tag %q", tag) newHistory := imageapi.TagEventList{} for i, tagEvent := range history.Items { glog.V(4).Infof("Checking tag event %d with image %q", i, tagEvent.Image) if tagEvent.Image != imageNode.Image.Name { glog.V(4).Infof("Tag event doesn't match deleted image - keeping") newHistory.Items = append(newHistory.Items, tagEvent) } else { glog.V(4).Infof("Tag event matches deleted image - removing reference") updatedTags.Insert(tag) } } if len(newHistory.Items) == 0 { glog.V(4).Infof("Removing tag %q from status.tags of ImageStream %s/%s", tag, stream.Namespace, stream.Name) delete(stream.Status.Tags, tag) } else { stream.Status.Tags[tag] = newHistory } } updatedStream, err := streamPruner.PruneImageStream(stream, imageNode.Image, updatedTags.List()) if err != nil { errs = append(errs, fmt.Errorf("error pruning image from stream: %v", err)) continue } streamNode.ImageStream = updatedStream } } glog.V(4).Infof("Done removing pruned image references from streams") return errs }
// imageIsPrunable returns true iff the image node only has weak references // from its predecessors to it. A weak reference to an image is a reference // from an image stream to an image where the image is not the current image // for a tag and the image stream is at least as old as the minimum pruning // age. func imageIsPrunable(g graph.Graph, imageNode *imagegraph.ImageNode) bool { onlyWeakReferences := true for _, n := range g.To(imageNode) { glog.V(4).Infof("Examining predecessor %#v", n) if !edgeKind(g, n, imageNode, WeakReferencedImageEdgeKind) { glog.V(4).Infof("Strong reference detected") onlyWeakReferences = false break } } return onlyWeakReferences }
// pruneManifests invokes manifestPruner.PruneManifest for each repository // manifest to be deleted from the registry. func pruneManifests(g graph.Graph, registryClient *http.Client, registryURL string, imageNodes []*imagegraph.ImageNode, manifestPruner ManifestPruner) []error { errs := []error{} for _, imageNode := range imageNodes { for _, n := range g.To(imageNode) { streamNode, ok := n.(*imagegraph.ImageStreamNode) if !ok { continue } stream := streamNode.ImageStream repoName := fmt.Sprintf("%s/%s", stream.Namespace, stream.Name) glog.V(4).Infof("Pruning manifest for registry %q, repo %q, image %q", registryURL, repoName, imageNode.Image.Name) if err := manifestPruner.PruneManifest(registryClient, registryURL, repoName, imageNode.Image.Name); err != nil { errs = append(errs, fmt.Errorf("error pruning manifest for registry %q, repo %q, image %q: %v", registryURL, repoName, imageNode.Image.Name, err)) } } } return errs }