func TestImageStreamAdmissionEvaluatorUsage(t *testing.T) { for _, tc := range []struct { name string oldSpec *imageapi.ImageStreamSpec oldStatus *imageapi.ImageStreamStatus newSpec *imageapi.ImageStreamSpec newStatus *imageapi.ImageStreamStatus expectedImages int64 }{ { name: "empty image stream", oldStatus: nil, newStatus: &imageapi.ImageStreamStatus{}, expectedImages: 0, }, { name: "new image stream with one image", oldStatus: nil, newStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith1LayerDigest), Image: baseImageWith1LayerDigest, }, }, }, }, }, expectedImages: 1, }, { name: "no change", oldSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "new": { Name: "new", From: &kapi.ObjectReference{ Kind: "ImageStreamImage", Namespace: "shared", Name: fmt.Sprintf("is@%s", miscImageDigest), }, }, }, }, oldStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith1LayerDigest), Image: baseImageWith1LayerDigest, }, }, }, }, }, newSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "new": { Name: "new", From: &kapi.ObjectReference{ Kind: "ImageStreamImage", Namespace: "shared", Name: fmt.Sprintf("is@%s", miscImageDigest), }, }, }, }, newStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith1LayerDigest), Image: baseImageWith1LayerDigest, }, }, }, }, }, // misc image is already present in common is expectedImages: 1, }, { name: "adding two new tags", oldStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith1LayerDigest), Image: baseImageWith1LayerDigest, }, }, }, }, }, newStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith1LayerDigest), Image: baseImageWith1LayerDigest, }, }, }, "foo": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/sharedlayer@%s", childImageWith2LayersDigest), Image: childImageWith2LayersDigest, }, }, }, "bar": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/sharedlayer@%s", baseImageWith2LayersDigest), Image: baseImageWith2LayersDigest, }, }, }, }, }, expectedImages: 3, }, { name: "adding an item and deleting the other tag", oldStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "foo": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/sharedlayer@%s", miscImageDigest), Image: miscImageDigest, }, }, }, "bar": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/sharedlayer@%s", baseImageWith2LayersDigest), Image: baseImageWith2LayersDigest, }, }, }, }, }, newStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "foo": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/sharedlayer@%s", childImageWith3LayersDigest), Image: childImageWith3LayersDigest, }, { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/sharedlayer@%s", miscImageDigest), Image: miscImageDigest, }, }, }, }, }, // misc image is already present in common is expectedImages: 1, }, { name: "adding a tag to spec", oldStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith1LayerDigest), Image: baseImageWith1LayerDigest, }, }, }, }, }, newSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "new": { Name: "new", From: &kapi.ObjectReference{ Kind: "ImageStreamImage", Namespace: "shared", Name: fmt.Sprintf("is@%s", baseImageWith2LayersDigest), }, }, }, }, newStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith1LayerDigest), Image: baseImageWith1LayerDigest, }, }, }, }, }, expectedImages: 2, }, { name: "adding a tag to status already present in spec", oldSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "latest": { Name: "new", From: &kapi.ObjectReference{ Kind: "ImageStreamImage", Namespace: "shared", Name: fmt.Sprintf("is@%s", childImageWith2LayersDigest), }, }, }, }, newSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "latest": { Name: "new", From: &kapi.ObjectReference{ Kind: "ImageStreamImage", Namespace: "shared", Name: fmt.Sprintf("is@%s", childImageWith2LayersDigest), }, }, }, }, newStatus: &imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "latest": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/is@%s", baseImageWith2LayersDigest), Image: childImageWith2LayersDigest, }, }, }, }, }, expectedImages: 1, }, { name: "refer to image in another namespace already present", newSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "misc": { Name: "misc", From: &kapi.ObjectReference{ Kind: "ImageStreamImage", Namespace: "shared", Name: fmt.Sprintf("is@%s", miscImageDigest), }, }, }, }, expectedImages: 0, }, { name: "refer to imagestreamimage in the same namespace", newSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "commonisi": { Name: "commonisi", From: &kapi.ObjectReference{ Kind: "ImageStreamImage", Name: fmt.Sprintf("common@%s", miscImageDigest), }, }, }, }, expectedImages: 0, }, { name: "refer to imagestreamtag in the same namespace", newSpec: &imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "commonist": { Name: "commonist", From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Name: "common:misc", }, }, }, }, expectedImages: 0, }, } { var newIS, oldIS *imageapi.ImageStream if tc.oldStatus != nil || tc.oldSpec != nil { oldIS = &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Namespace: "test", Name: "is", }, } if tc.oldSpec != nil { oldIS.Spec = *tc.oldSpec } if tc.oldStatus != nil { oldIS.Status = *tc.oldStatus } } if tc.newStatus != nil || tc.newSpec != nil { newIS = &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Namespace: "test", Name: "is", }, } if tc.newSpec != nil { newIS.Spec = *tc.newSpec } if tc.newStatus != nil { newIS.Status = *tc.newStatus } } commonIS := imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Namespace: "test", Name: "common", }, Status: imageapi.ImageStreamStatus{ Tags: map[string]imageapi.TagEventList{ "misc": { Items: []imageapi.TagEvent{ { DockerImageReference: fmt.Sprintf("172.30.12.34:5000/test/common@%s", miscImageDigest), Image: miscImageDigest, }, }, }, }, }, } iss := []imageapi.ImageStream{commonIS} if oldIS != nil { iss = append(iss, *oldIS) } fakeClient := &testclient.Fake{} fakeClient.AddReactor("get", "imagestreams", getFakeImageStreamGetHandler(t, iss...)) fakeClient.AddReactor("list", "imagestreams", getFakeImageStreamListHandler(t, iss...)) fakeClient.AddReactor("get", "images", getFakeImageGetHandler(t, "test")) evaluator := NewImageStreamAdmissionEvaluator(fakeClient) usage := evaluator.Usage(newIS) if len(usage) != len(expectedResources) { t.Errorf("[%s]: got unexpected number of computed resources: %d != %d", tc.name, len(usage), len(expectedResources)) } expectedUsage := kapi.ResourceList{ imageapi.ResourceImages: *resource.NewQuantity(tc.expectedImages, resource.DecimalSI), } masked := kquota.Mask(usage, expectedResources) if len(masked) != len(expectedUsage) { for k := range usage { if _, exists := masked[k]; !exists { t.Errorf("[%s]: got unexpected resource %q from Usage() method", tc.name, k) } } for k := range expectedUsage { if _, exists := masked[k]; !exists { t.Errorf("[%s]: expected resource %q not computed", tc.name, k) } } } for rname, expectedValue := range expectedUsage { if v, exists := masked[rname]; exists { if v.Cmp(expectedValue) != 0 { t.Errorf("[%s]: got unexpected usage for %q: %s != %s", tc.name, rname, v.String(), expectedValue.String()) } } } } }