Browse code

make imagestreamtag usage consistent

deads2k authored on 2015/06/26 21:26:42
Showing 9 changed files
... ...
@@ -293,7 +293,7 @@ func TestGraph(t *testing.T) {
293 293
 
294 294
 	t.Log(g)
295 295
 
296
-	ir, dc, bc, other := 0, 0, 0, 0
296
+	ist, dc, bc, other := 0, 0, 0, 0
297 297
 	for _, node := range g.NodeList() {
298 298
 		switch g.Object(node).(type) {
299 299
 		case *deployapi.DeploymentConfig:
... ...
@@ -306,19 +306,18 @@ func TestGraph(t *testing.T) {
306 306
 				t.Fatalf("unexpected kind: %v", g.Kind(node))
307 307
 			}
308 308
 			bc++
309
-		case *imageapi.ImageStream:
310
-			// TODO resolve this check for 2 kinds, since both have the same object type
311
-			if g.Kind(node) != imagegraph.ImageStreamNodeKind && g.Kind(node) != imagegraph.ImageStreamTagNodeKind {
309
+		case *imageapi.ImageStreamTag:
310
+			if g.Kind(node) != imagegraph.ImageStreamTagNodeKind {
312 311
 				t.Fatalf("unexpected kind: %v", g.Kind(node))
313 312
 			}
314
-			ir++
313
+			ist++
315 314
 		default:
316 315
 			other++
317 316
 		}
318 317
 	}
319 318
 
320
-	if dc != 2 || bc != 3 || ir != 3 || other != 12 {
321
-		t.Errorf("unexpected nodes: %d %d %d %d", dc, bc, ir, other)
319
+	if dc != 2 || bc != 3 || ist != 3 || other != 12 {
320
+		t.Errorf("unexpected nodes: %d %d %d %d", dc, bc, ist, other)
322 321
 	}
323 322
 	for _, edge := range g.EdgeList() {
324 323
 		if g.EdgeKind(edge) == osgraph.UnknownEdgeKind {
... ...
@@ -329,7 +328,7 @@ func TestGraph(t *testing.T) {
329 329
 	// imagestreamtag default/other:base-image
330 330
 	istID := 0
331 331
 	for _, node := range g.NodeList() {
332
-		if g.Name(node) == "<imagestreamtag default/other:base-image>" {
332
+		if g.Name(node) == "ImageStreamTag|default/other:base-image" {
333 333
 			istID = node.ID()
334 334
 			break
335 335
 		}
... ...
@@ -32,7 +32,7 @@ func (n ServiceNode) Object() interface{} {
32 32
 }
33 33
 
34 34
 func (n ServiceNode) String() string {
35
-	return fmt.Sprintf("<service %s/%s>", n.Namespace, n.Name)
35
+	return string(ServiceNodeName(n.Service))
36 36
 }
37 37
 
38 38
 func (*ServiceNode) Kind() string {
... ...
@@ -53,7 +53,7 @@ func (n PodNode) Object() interface{} {
53 53
 }
54 54
 
55 55
 func (n PodNode) String() string {
56
-	return fmt.Sprintf("<pod %s/%s>", n.Namespace, n.Name)
56
+	return string(PodNodeName(n.Pod))
57 57
 }
58 58
 
59 59
 func (n PodNode) UniqueName() osgraph.UniqueName {
... ...
@@ -105,7 +105,7 @@ func (n ReplicationControllerNode) Object() interface{} {
105 105
 }
106 106
 
107 107
 func (n ReplicationControllerNode) String() string {
108
-	return fmt.Sprintf("<replicationcontroller %s/%s>", n.Namespace, n.Name)
108
+	return string(ReplicationControllerNodeName(n.ReplicationController))
109 109
 }
110 110
 
111 111
 func (n ReplicationControllerNode) UniqueName() osgraph.UniqueName {
... ...
@@ -26,7 +26,7 @@ func AddInputOutputEdges(g osgraph.MutableUniqueGraph, node *buildgraph.BuildCon
26 26
 	to := output.To
27 27
 	switch {
28 28
 	case to != nil && len(to.Name) > 0:
29
-		out := imagegraph.EnsureImageStreamTagNode(g, defaultNamespace(to.Namespace, node.BuildConfig.Namespace), to.Name, output.Tag)
29
+		out := imagegraph.FindOrCreateSyntheticImageStreamTagNode(g, imagegraph.MakeImageStreamTagObjectMeta(defaultNamespace(to.Namespace, node.BuildConfig.Namespace), to.Name, output.Tag))
30 30
 		g.AddEdge(node, out, BuildOutputEdgeKind)
31 31
 	case len(output.DockerImageReference) > 0:
32 32
 		out := imagegraph.EnsureDockerRepositoryNode(g, output.DockerImageReference, output.Tag)
... ...
@@ -49,11 +49,11 @@ func AddInputOutputEdges(g osgraph.MutableUniqueGraph, node *buildgraph.BuildCon
49 49
 			}
50 50
 		case "ImageStream":
51 51
 			tag := imageapi.DefaultImageTag
52
-			in := imagegraph.EnsureImageStreamTagNode(g, defaultNamespace(from.Namespace, node.BuildConfig.Namespace), from.Name, tag)
52
+			in := imagegraph.FindOrCreateSyntheticImageStreamTagNode(g, imagegraph.MakeImageStreamTagObjectMeta(defaultNamespace(from.Namespace, node.BuildConfig.Namespace), from.Name, tag))
53 53
 			g.AddEdge(in, node, BuildInputImageEdgeKind)
54 54
 		case "ImageStreamTag":
55 55
 			name, tag, _ := imageapi.SplitImageStreamTag(from.Name)
56
-			in := imagegraph.EnsureImageStreamTagNode(g, defaultNamespace(from.Namespace, node.BuildConfig.Namespace), name, tag)
56
+			in := imagegraph.FindOrCreateSyntheticImageStreamTagNode(g, imagegraph.MakeImageStreamTagObjectMeta(defaultNamespace(from.Namespace, node.BuildConfig.Namespace), name, tag))
57 57
 			g.AddEdge(in, node, BuildInputImageEdgeKind)
58 58
 		case "ImageStreamImage":
59 59
 			glog.V(4).Infof("Ignoring ImageStreamImage reference in BuildConfig %s/%s", node.BuildConfig.Namespace, node.BuildConfig.Name)
... ...
@@ -34,7 +34,7 @@ func (n BuildConfigNode) Object() interface{} {
34 34
 }
35 35
 
36 36
 func (n BuildConfigNode) String() string {
37
-	return fmt.Sprintf("<buildconfig %s/%s>", n.Namespace, n.Name)
37
+	return string(BuildConfigNodeName(n.BuildConfig))
38 38
 }
39 39
 
40 40
 func (*BuildConfigNode) Kind() string {
... ...
@@ -57,10 +57,7 @@ type SourceRepositoryNode struct {
57 57
 }
58 58
 
59 59
 func (n SourceRepositoryNode) String() string {
60
-	if n.Source.Git != nil {
61
-		return fmt.Sprintf("<sourcerepository %s#%s>", n.Source.Git.URI, n.Source.Git.Ref)
62
-	}
63
-	return fmt.Sprintf("<source repository unknown>")
60
+	return string(SourceRepositoryNodeName(n.Source))
64 61
 }
65 62
 
66 63
 func (SourceRepositoryNode) Kind() string {
... ...
@@ -81,7 +78,7 @@ func (n BuildNode) Object() interface{} {
81 81
 }
82 82
 
83 83
 func (n BuildNode) String() string {
84
-	return fmt.Sprintf("<build %s/%s>", n.Build.Namespace, n.Build.Name)
84
+	return string(BuildNodeName(n.Build))
85 85
 }
86 86
 
87 87
 func (*BuildNode) Kind() string {
... ...
@@ -42,6 +42,11 @@ func (d *ProjectStatusDescriber) MakeGraph(namespace string) (osgraph.Graph, err
42 42
 		return g, err
43 43
 	}
44 44
 
45
+	iss, err := d.C.ImageStreams(namespace).List(labels.Everything(), fields.Everything())
46
+	if err != nil {
47
+		return g, err
48
+	}
49
+
45 50
 	bcs, err := d.C.BuildConfigs(namespace).List(labels.Everything(), fields.Everything())
46 51
 	if err != nil {
47 52
 		return g, err
... ...
@@ -64,6 +69,10 @@ func (d *ProjectStatusDescriber) MakeGraph(namespace string) (osgraph.Graph, err
64 64
 		rcs = &kapi.ReplicationControllerList{}
65 65
 	}
66 66
 
67
+	for i := range iss.Items {
68
+		imagegraph.EnsureImageStreamNode(g, &iss.Items[i])
69
+		imagegraph.EnsureAllImageStreamTagNodes(g, &iss.Items[i])
70
+	}
67 71
 	for i := range bcs.Items {
68 72
 		build := buildgraph.EnsureBuildConfigNode(g, &bcs.Items[i])
69 73
 		buildedges.AddInputOutputEdges(g, build)
... ...
@@ -214,10 +223,10 @@ func describeImageInPipeline(pipeline graphview.ImagePipeline, namespace string)
214 214
 func describeImageTagInPipeline(image graphview.ImageTagLocation, namespace string) string {
215 215
 	switch t := image.(type) {
216 216
 	case *imagegraph.ImageStreamTagNode:
217
-		if t.ImageStream.Namespace != namespace {
217
+		if t.ImageStreamTag.Namespace != namespace {
218 218
 			return image.ImageSpec()
219 219
 		}
220
-		return fmt.Sprintf("%s:%s", t.ImageStream.Name, image.ImageTag())
220
+		return t.ImageStreamTag.Name
221 221
 	default:
222 222
 		return image.ImageSpec()
223 223
 	}
... ...
@@ -36,7 +36,8 @@ func AddTriggerEdges(g osgraph.MutableUniqueGraph, node *deploygraph.DeploymentC
36 36
 				if len(image.From.Name) == 0 {
37 37
 					return
38 38
 				}
39
-				in := imagegraph.EnsureImageStreamTagNode(g, image.From.Namespace, image.From.Name, image.FromTag)
39
+
40
+				in := imagegraph.FindOrCreateSyntheticImageStreamTagNode(g, imagegraph.MakeImageStreamTagObjectMeta(image.From.Namespace, image.From.Name, image.FromTag))
40 41
 				g.AddEdge(in, node, TriggersDeploymentEdgeKind)
41 42
 				return
42 43
 			}
... ...
@@ -1,7 +1,6 @@
1 1
 package nodes
2 2
 
3 3
 import (
4
-	"fmt"
5 4
 	"reflect"
6 5
 
7 6
 	kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
... ...
@@ -31,7 +30,7 @@ func (n DeploymentConfigNode) Object() interface{} {
31 31
 }
32 32
 
33 33
 func (n DeploymentConfigNode) String() string {
34
-	return fmt.Sprintf("<deploymentconfig %s/%s>", n.Namespace, n.Name)
34
+	return string(DeploymentConfigNodeName(n.DeploymentConfig))
35 35
 }
36 36
 
37 37
 func (*DeploymentConfigNode) Kind() string {
... ...
@@ -1,8 +1,6 @@
1 1
 package nodes
2 2
 
3 3
 import (
4
-	"strings"
5
-
6 4
 	"github.com/gonum/graph"
7 5
 
8 6
 	kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
... ...
@@ -20,13 +18,30 @@ func EnsureImageNode(g osgraph.MutableUniqueGraph, img *imageapi.Image) graph.No
20 20
 	)
21 21
 }
22 22
 
23
+// EnsureAllImageStreamTagNodes creates all the ImageStreamTagNodes that are guaranteed to be present based on the ImageStream.
24
+// This is different than inferring the presence of an object, since the IST is an object derived from a join between the ImageStream
25
+// and the Image it references.
26
+func EnsureAllImageStreamTagNodes(g osgraph.MutableUniqueGraph, is *imageapi.ImageStream) []*ImageStreamTagNode {
27
+	ret := []*ImageStreamTagNode{}
28
+
29
+	for tag := range is.Status.Tags {
30
+		ist := &imageapi.ImageStreamTag{}
31
+		ist.Namespace = is.Namespace
32
+		ist.Name = imageapi.JoinImageStreamTag(is.Name, tag)
33
+
34
+		istNode := EnsureImageStreamTagNode(g, ist)
35
+		ret = append(ret, istNode)
36
+	}
37
+
38
+	return ret
39
+}
40
+
23 41
 func FindImage(g osgraph.MutableUniqueGraph, imageName string) graph.Node {
24 42
 	return g.Find(ImageNodeName(&imageapi.Image{ObjectMeta: kapi.ObjectMeta{Name: imageName}}))
25 43
 }
26 44
 
27 45
 // EnsureDockerRepositoryNode adds the named Docker repository tag reference to the graph if it does
28
-// not already exist. If the reference is invalid, the Name field of the graph will be
29
-// used directly.
46
+// not already exist. If the reference is invalid, the Name field of the graph will be used directly.
30 47
 func EnsureDockerRepositoryNode(g osgraph.MutableUniqueGraph, name, tag string) graph.Node {
31 48
 	ref, err := imageapi.ParseDockerImageReference(name)
32 49
 	if err == nil {
... ...
@@ -54,27 +69,35 @@ func EnsureDockerRepositoryNode(g osgraph.MutableUniqueGraph, name, tag string)
54 54
 	)
55 55
 }
56 56
 
57
-// EnsureImageStreamTagNode adds a graph node for the specific tag in an Image Stream if it
58
-// does not already exist.
59
-func EnsureImageStreamTagNode(g osgraph.MutableUniqueGraph, namespace, name, tag string) graph.Node {
60
-	if len(tag) == 0 {
61
-		tag = imageapi.DefaultImageTag
62
-	}
63
-	if strings.Contains(name, ":") {
64
-		panic(name)
65
-	}
66
-	is := &imageapi.ImageStream{
57
+// MakeImageStreamTagObjectMeta returns an ImageStreamTag that has enough information to join the graph, but it is not
58
+// based on a full IST object.  This can be used to properly initialize the graph without having to retrieve all ISTs
59
+func MakeImageStreamTagObjectMeta(namespace, name, tag string) *imageapi.ImageStreamTag {
60
+	return &imageapi.ImageStreamTag{
67 61
 		ObjectMeta: kapi.ObjectMeta{
68 62
 			Namespace: namespace,
69
-			Name:      name,
63
+			Name:      imageapi.JoinImageStreamTag(name, tag),
70 64
 		},
71 65
 	}
66
+}
67
+
68
+// EnsureImageStreamTagNode adds a graph node for the specific tag in an Image Stream if it does not already exist.
69
+func EnsureImageStreamTagNode(g osgraph.MutableUniqueGraph, ist *imageapi.ImageStreamTag) *ImageStreamTagNode {
72 70
 	return osgraph.EnsureUnique(g,
73
-		ImageStreamTagNodeName(is, tag),
71
+		ImageStreamTagNodeName(ist),
74 72
 		func(node osgraph.Node) graph.Node {
75
-			return &ImageStreamTagNode{node, is, tag}
73
+			return &ImageStreamTagNode{node, ist, false}
76 74
 		},
77
-	)
75
+	).(*ImageStreamTagNode)
76
+}
77
+
78
+// FindOrCreateSyntheticImageStreamTagNode returns the existing ISTNode or creates a synthetic node in its place
79
+func FindOrCreateSyntheticImageStreamTagNode(g osgraph.MutableUniqueGraph, ist *imageapi.ImageStreamTag) *ImageStreamTagNode {
80
+	return osgraph.EnsureUnique(g,
81
+		ImageStreamTagNodeName(ist),
82
+		func(node osgraph.Node) graph.Node {
83
+			return &ImageStreamTagNode{node, ist, true}
84
+		},
85
+	).(*ImageStreamTagNode)
78 86
 }
79 87
 
80 88
 // EnsureImageStreamNode adds a graph node for the Image Stream if it does not already exist.
... ...
@@ -87,10 +110,6 @@ func EnsureImageStreamNode(g osgraph.MutableUniqueGraph, stream *imageapi.ImageS
87 87
 	)
88 88
 }
89 89
 
90
-func FindImageStream(g osgraph.MutableUniqueGraph, stream *imageapi.ImageStream) graph.Node {
91
-	return g.Find(ImageStreamNodeName(stream))
92
-}
93
-
94 90
 // EnsureImageLayerNode adds a graph node for the layer if it does not already exist.
95 91
 func EnsureImageLayerNode(g osgraph.MutableUniqueGraph, layer string) graph.Node {
96 92
 	return osgraph.EnsureUnique(g,
... ...
@@ -32,37 +32,44 @@ func (n ImageStreamNode) Object() interface{} {
32 32
 }
33 33
 
34 34
 func (n ImageStreamNode) String() string {
35
-	return fmt.Sprintf("<imagestream %s/%s>", n.Namespace, n.Name)
35
+	return string(ImageStreamNodeName(n.ImageStream))
36 36
 }
37 37
 
38 38
 func (*ImageStreamNode) Kind() string {
39 39
 	return ImageStreamNodeKind
40 40
 }
41 41
 
42
-func ImageStreamTagNodeName(o *imageapi.ImageStream, tag string) osgraph.UniqueName {
43
-	return osgraph.UniqueName(fmt.Sprintf("%s|%s/%s:%s", ImageStreamTagNodeKind, o.Namespace, o.Name, tag))
42
+func ImageStreamTagNodeName(o *imageapi.ImageStreamTag) osgraph.UniqueName {
43
+	return osgraph.GetUniqueRuntimeObjectNodeName(ImageStreamTagNodeKind, o)
44 44
 }
45 45
 
46 46
 type ImageStreamTagNode struct {
47 47
 	osgraph.Node
48
-	*imageapi.ImageStream
49
-	Tag string
48
+	*imageapi.ImageStreamTag
49
+
50
+	Synthetic bool
51
+}
52
+
53
+func (n ImageStreamTagNode) IsSynthetic() bool {
54
+	return n.Synthetic
50 55
 }
51 56
 
52 57
 func (n ImageStreamTagNode) ImageSpec() string {
53
-	return imageapi.DockerImageReference{Namespace: n.Namespace, Name: n.Name, Tag: n.Tag}.String()
58
+	name, tag, _ := imageapi.SplitImageStreamTag(n.ImageStreamTag.Name)
59
+	return imageapi.DockerImageReference{Namespace: n.Namespace, Name: name, Tag: tag}.String()
54 60
 }
55 61
 
56 62
 func (n ImageStreamTagNode) ImageTag() string {
57
-	return n.Tag
63
+	_, tag, _ := imageapi.SplitImageStreamTag(n.ImageStreamTag.Name)
64
+	return tag
58 65
 }
59 66
 
60 67
 func (n ImageStreamTagNode) Object() interface{} {
61
-	return n.ImageStream
68
+	return n.ImageStreamTag
62 69
 }
63 70
 
64 71
 func (n ImageStreamTagNode) String() string {
65
-	return fmt.Sprintf("<imagestreamtag %s/%s:%s>", n.Namespace, n.Name, n.Tag)
72
+	return string(ImageStreamTagNodeName(n.ImageStreamTag))
66 73
 }
67 74
 
68 75
 func (*ImageStreamTagNode) Kind() string {
... ...
@@ -87,7 +94,7 @@ func (n DockerImageRepositoryNode) ImageTag() string {
87 87
 }
88 88
 
89 89
 func (n DockerImageRepositoryNode) String() string {
90
-	return fmt.Sprintf("<dockerrepository %s>", n.Ref.String())
90
+	return string(DockerImageRepositoryNodeName(n.Ref))
91 91
 }
92 92
 
93 93
 func (*DockerImageRepositoryNode) Kind() string {
... ...
@@ -108,7 +115,7 @@ func (n ImageNode) Object() interface{} {
108 108
 }
109 109
 
110 110
 func (n ImageNode) String() string {
111
-	return fmt.Sprintf("<image %s>", n.Image.Name)
111
+	return string(ImageNodeName(n.Image))
112 112
 }
113 113
 
114 114
 func (*ImageNode) Kind() string {
... ...
@@ -129,7 +136,7 @@ func (n ImageLayerNode) Object() interface{} {
129 129
 }
130 130
 
131 131
 func (n ImageLayerNode) String() string {
132
-	return fmt.Sprintf("<image layer %s>", n.Layer)
132
+	return string(ImageLayerNodeName(n.Layer))
133 133
 }
134 134
 
135 135
 func (*ImageLayerNode) Kind() string {