// Edges are added to the graph from each predecessor (pod or replication // controller) to the images specified by the pod spec's list of containers, as // long as the image is managed by OpenShift. func addPodSpecToGraph(g graph.Graph, spec *kapi.PodSpec, predecessor gonum.Node) { for j := range spec.Containers { container := spec.Containers[j] glog.V(4).Infof("Examining container image %q", container.Image) ref, err := imageapi.ParseDockerImageReference(container.Image) if err != nil { util.HandleError(fmt.Errorf("unable to parse DockerImageReference %q: %v", container.Image, err)) continue } if len(ref.ID) == 0 { glog.V(4).Infof("%q has no image ID", container.Image) continue } imageNode := graph.FindImage(g, ref.ID) if imageNode == nil { glog.Infof("Unable to find image %q in the graph", ref.ID) continue } glog.V(4).Infof("Adding edge from pod to image") g.AddEdge(predecessor, imageNode, graph.ReferencedImageGraphEdgeKind) } }
// addImageStreamsToGraph adds all the streams to the graph. The most recent n // image revisions for a tag will be preserved, where n is specified by the // algorithm's tagRevisionsToKeep. Image revisions older than n are candidates // for pruning. if the image stream's age is at least as old as the minimum // threshold in algorithm. Otherwise, if the image stream is younger than the // threshold, all image revisions for that stream are ineligible for pruning. // // addImageStreamsToGraph also adds references from each stream to all the // layers it references (via each image a stream references). func addImageStreamsToGraph(g graph.Graph, streams *imageapi.ImageStreamList, algorithm pruneAlgorithm) { for i := range streams.Items { stream := &streams.Items[i] glog.V(4).Infof("Examining ImageStream %s/%s", stream.Namespace, stream.Name) // use a weak reference for old image revisions by default oldImageRevisionReferenceKind := graph.WeakReferencedImageGraphEdgeKind age := util.Now().Sub(stream.CreationTimestamp.Time) if age < algorithm.keepYoungerThan { // stream's age is below threshold - use a strong reference for old image revisions instead glog.V(4).Infof("Stream %s/%s is below age threshold - none of its images are eligible for pruning", stream.Namespace, stream.Name) oldImageRevisionReferenceKind = graph.ReferencedImageGraphEdgeKind } glog.V(4).Infof("Adding ImageStream %s/%s to graph", stream.Namespace, stream.Name) isNode := graph.ImageStream(g, stream) imageStreamNode := isNode.(*graph.ImageStreamNode) for tag, history := range stream.Status.Tags { for i := range history.Items { n := graph.FindImage(g, history.Items[i].Image) if n == nil { glog.V(1).Infof("Unable to find image %q in graph (from tag=%q, revision=%d, dockerImageReference=%s)", history.Items[i].Image, tag, i, history.Items[i].DockerImageReference) continue } imageNode := n.(*graph.ImageNode) var kind int switch { case i < algorithm.tagRevisionsToKeep: kind = graph.ReferencedImageGraphEdgeKind default: kind = oldImageRevisionReferenceKind } glog.V(4).Infof("Checking for existing strong reference from stream %s/%s to image %s", stream.Namespace, stream.Name, imageNode.Image.Name) if edge := g.EdgeBetween(imageStreamNode, imageNode); edge != nil && g.EdgeKind(edge) == graph.ReferencedImageGraphEdgeKind { glog.V(4).Infof("Strong reference found") continue } glog.V(4).Infof("Adding edge (kind=%d) from %q to %q", kind, imageStreamNode.UniqueName.UniqueName(), imageNode.UniqueName.UniqueName()) g.AddEdge(imageStreamNode, imageNode, kind) glog.V(4).Infof("Adding stream->layer references") // add stream -> layer references so we can prune them later for _, s := range g.Successors(imageNode) { if g.Kind(s) != graph.ImageLayerGraphKind { continue } glog.V(4).Infof("Adding reference from stream %q to layer %q", stream.Name, s.(*graph.ImageLayerNode).Layer) g.AddEdge(imageStreamNode, s, graph.ReferencedImageLayerGraphEdgeKind) } } } } }
// Edges are added to the graph from each predecessor (build or build config) // to the image specified by strategy.from, as long as the image is managed by // OpenShift. func addBuildStrategyImageReferencesToGraph(g graph.Graph, strategy buildapi.BuildStrategy, predecessor gonum.Node) { glog.V(4).Infof("Examining build strategy with type %q", strategy.Type) from := buildutil.GetImageStreamForStrategy(strategy) if from == nil { glog.V(4).Infof("Unable to determine 'from' reference - skipping") return } glog.V(4).Infof("Examining build strategy with from: %#v", from) var imageID string switch from.Kind { case "ImageStreamImage": _, id, err := imagestreamimage.ParseNameAndID(from.Name) if err != nil { glog.V(2).Infof("Error parsing ImageStreamImage name %q: %v - skipping", from.Name, err) return } imageID = id case "DockerImage": ref, err := imageapi.ParseDockerImageReference(from.Name) if err != nil { glog.V(2).Infof("Error parsing DockerImage name %q: %v - skipping", from.Name, err) return } imageID = ref.ID default: return } glog.V(4).Infof("Looking for image %q in graph", imageID) imageNode := graph.FindImage(g, imageID) if imageNode == nil { glog.V(4).Infof("Unable to find image %q in graph - skipping", imageID) return } glog.V(4).Infof("Adding edge from %v to %v", predecessor, imageNode) g.AddEdge(predecessor, imageNode, graph.ReferencedImageGraphEdgeKind) }