func TestDeletingImagePruner(t *testing.T) { flag.Lookup("v").Value.Set(fmt.Sprint(*logLevel)) tests := map[string]struct { imageDeletionError error }{ "no error": {}, "delete error": { imageDeletionError: fmt.Errorf("foo"), }, } for name, test := range tests { imageClient := testclient.Fake{ Err: test.imageDeletionError, } imagePruner := NewDeletingImagePruner(imageClient.Images()) err := imagePruner.PruneImage(&imageapi.Image{ObjectMeta: kapi.ObjectMeta{Name: "id2"}}) if test.imageDeletionError != nil { if e, a := test.imageDeletionError, err; e != a { t.Errorf("%s: err: expected %v, got %v", name, e, a) } continue } if e, a := 1, len(imageClient.Actions); e != a { t.Errorf("%s: expected %d actions, got %d: %#v", name, e, a, imageClient.Actions) continue } if e, a := "delete-image", imageClient.Actions[0].Action; e != a { t.Errorf("%s: expected action %q, got %q", name, e, a) } } }
func noAction(kubeClient *fake.Clientset, originClient *testclient.Fake) string { if len(kubeClient.Actions()) != 0 { return fmt.Sprintf("unexpected actions: %v", kubeClient.Actions()) } if len(originClient.Actions()) != 0 { return fmt.Sprintf("unexpected actions: %v", originClient.Actions()) } return "" }
func extractDeletedGroups(tc *testclient.Fake) []string { ret := []string{} for _, genericAction := range tc.Actions() { switch action := genericAction.(type) { case core.DeleteAction: ret = append(ret, action.GetName()) } } return ret }
func extractActualGroups(tc *testclient.Fake) []*userapi.Group { ret := []*userapi.Group{} for _, genericAction := range tc.Actions() { switch action := genericAction.(type) { case ktestclient.CreateAction: ret = append(ret, action.GetObject().(*userapi.Group)) case ktestclient.UpdateAction: ret = append(ret, action.GetObject().(*userapi.Group)) } } return ret }
func checkResult(t *testing.T, err error, c *testclient.Fake, admitter *StatusAdmitter, targetHost string, targetObjTime unversioned.Time, targetCachedTime *time.Time, ingressInd int, actionInd int) *routeapi.Route { if err != nil { t.Fatalf("unexpected error: %v", err) } if len(c.Actions()) != actionInd+1 { t.Fatalf("unexpected actions: %#v", c.Actions()) } action := c.Actions()[actionInd] if action.GetVerb() != "update" || action.GetResource() != "routes" || action.GetSubresource() != "status" { t.Fatalf("unexpected action: %#v", action) } obj := c.Actions()[actionInd].(ktestclient.UpdateAction).GetObject().(*routeapi.Route) if len(obj.Status.Ingress) != ingressInd+1 || obj.Status.Ingress[ingressInd].Host != targetHost { t.Fatalf("expected route reset: expected %q / actual %q -- %#v", targetHost, obj.Status.Ingress[ingressInd].Host, obj) } condition := obj.Status.Ingress[ingressInd].Conditions[0] if condition.LastTransitionTime == nil || *condition.LastTransitionTime != targetObjTime || condition.Status != kapi.ConditionTrue || condition.Reason != "" { t.Fatalf("%s: unexpected condition: %#v", targetHost, condition) } if targetCachedTime == nil { if v, ok := admitter.expected.Peek(types.UID("uid1")); ok { t.Fatalf("expected empty time: %#v", v) } } else { if v, ok := admitter.expected.Peek(types.UID("uid1")); !ok || !reflect.DeepEqual(v, *targetCachedTime) { t.Fatalf("did not record last modification time: %#v %#v", admitter.expected, v) } } return obj }
func makePass(t *testing.T, host string, admitter *StatusAdmitter, srcObj *routeapi.Route, expectUpdate bool, conflict bool) *routeapi.Route { // initialize a new client var c *testclient.Fake if conflict { c = testclient.NewSimpleFake(&(errors.NewConflict(kapi.Resource("Route"), "route1", nil).ErrStatus)) } else { c = testclient.NewSimpleFake(&routeapi.Route{}) } admitter.client = c inputObjRaw, err := kapi.Scheme.DeepCopy(srcObj) if err != nil { t.Fatalf("unexpected error: %v", err) } inputObj := inputObjRaw.(*routeapi.Route) inputObj.Spec.Host = host err = admitter.HandleRoute(watch.Modified, inputObj) if expectUpdate { now := nowFn() var nowTime *time.Time if !conflict { nowTime = &now.Time } return checkResult(t, err, c, admitter, inputObj.Spec.Host, now, nowTime, 0, 0) } else { if err != nil { t.Fatalf("unexpected error: %v", err) } // expect the last HandleRoute not to have performed any actions if len(c.Actions()) != 0 { t.Fatalf("unexpected actions: %#v", c) } return nil } }
func TestDeletingImagePruner(t *testing.T) { flag.Lookup("v").Value.Set(fmt.Sprint(*logLevel)) tests := map[string]struct { imageDeletionError error }{ "no error": {}, "delete error": { imageDeletionError: fmt.Errorf("foo"), }, } for name, test := range tests { imageClient := testclient.Fake{} imageClient.AddReactor("delete", "images", func(action ktc.Action) (handled bool, ret runtime.Object, err error) { return true, nil, test.imageDeletionError }) imagePruner := NewDeletingImagePruner(imageClient.Images()) err := imagePruner.PruneImage(&imageapi.Image{ObjectMeta: kapi.ObjectMeta{Name: "id2"}}) if test.imageDeletionError != nil { if e, a := test.imageDeletionError, err; e != a { t.Errorf("%s: err: expected %v, got %v", name, e, a) } continue } if e, a := 1, len(imageClient.Actions()); e != a { t.Errorf("%s: expected %d actions, got %d: %#v", name, e, a, imageClient.Actions()) continue } if !imageClient.Actions()[0].Matches("delete", "images") { t.Errorf("%s: expected action %s, got %v", name, "delete-images", imageClient.Actions()[0]) } } }
func TestCreateImageImport(t *testing.T) { testCases := map[string]struct { name string from string stream *imageapi.ImageStream all bool confirm bool insecure *bool err string expectedImages []imageapi.ImageImportSpec expectedRepository *imageapi.RepositoryImportSpec }{ "import from non-existing": { name: "nonexisting", err: "pass --confirm to create and import", }, "confirmed import from non-existing": { name: "nonexisting", confirm: true, expectedImages: []imageapi.ImageImportSpec{{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "nonexisting"}, To: &kapi.LocalObjectReference{Name: "latest"}, }}, }, "confirmed import all from non-existing": { name: "nonexisting", all: true, confirm: true, expectedRepository: &imageapi.RepositoryImportSpec{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "nonexisting"}, }, }, "import from .spec.dockerImageRepository": { name: "testis", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ DockerImageRepository: "repo.com/somens/someimage", Tags: make(map[string]imageapi.TagReference), }, }, expectedImages: []imageapi.ImageImportSpec{{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage"}, To: &kapi.LocalObjectReference{Name: "latest"}, }}, }, "import all from .spec.dockerImageRepository": { name: "testis", all: true, stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ DockerImageRepository: "repo.com/somens/someimage", Tags: make(map[string]imageapi.TagReference), }, }, expectedRepository: &imageapi.RepositoryImportSpec{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage"}, }, }, "import all from .spec.dockerImageRepository with different from": { name: "testis", from: "totally_different_spec", all: true, err: "different import spec", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ DockerImageRepository: "repo.com/somens/someimage", Tags: make(map[string]imageapi.TagReference), }, }, }, "import all from .spec.dockerImageRepository with confirmed different from": { name: "testis", from: "totally/different/spec", all: true, confirm: true, stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ DockerImageRepository: "repo.com/somens/someimage", Tags: make(map[string]imageapi.TagReference), }, }, expectedRepository: &imageapi.RepositoryImportSpec{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "totally/different/spec"}, }, }, "import all from .spec.tags": { name: "testis", all: true, stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "latest": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}}, "other": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:other"}}, }, }, }, expectedImages: []imageapi.ImageImportSpec{ { From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}, To: &kapi.LocalObjectReference{Name: "latest"}, }, { From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:other"}, To: &kapi.LocalObjectReference{Name: "other"}, }, }, }, "import all from .spec.tags with insecure annotation": { name: "testis", all: true, stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", Annotations: map[string]string{imageapi.InsecureRepositoryAnnotation: "true"}, }, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "latest": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}}, "other": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:other"}}, }, }, }, expectedImages: []imageapi.ImageImportSpec{ { From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}, To: &kapi.LocalObjectReference{Name: "latest"}, ImportPolicy: imageapi.TagImportPolicy{Insecure: true}, }, { From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:other"}, To: &kapi.LocalObjectReference{Name: "other"}, ImportPolicy: imageapi.TagImportPolicy{Insecure: true}, }, }, }, "import all from .spec.tags with insecure flag": { name: "testis", all: true, insecure: newBool(true), stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "latest": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}}, "other": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:other"}}, }, }, }, expectedImages: []imageapi.ImageImportSpec{ { From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}, To: &kapi.LocalObjectReference{Name: "latest"}, ImportPolicy: imageapi.TagImportPolicy{Insecure: true}, }, { From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:other"}, To: &kapi.LocalObjectReference{Name: "other"}, ImportPolicy: imageapi.TagImportPolicy{Insecure: true}, }, }, }, "import all from .spec.tags no DockerImage tags": { name: "testis", all: true, err: "does not have tags pointing to external docker images", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "latest": {From: &kapi.ObjectReference{Kind: "ImageStreamTag", Name: "otheris:latest"}}, }, }, }, }, "empty image stream": { name: "testis", err: "does not have valid docker images", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, }, }, "import latest tag": { name: "testis:latest", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", }, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "latest": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}}, }, }, }, expectedImages: []imageapi.ImageImportSpec{{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}, To: &kapi.LocalObjectReference{Name: "latest"}, }}, }, "import existing tag": { name: "testis:existing", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", }, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "existing": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}}, }, }, }, expectedImages: []imageapi.ImageImportSpec{{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}, To: &kapi.LocalObjectReference{Name: "existing"}, }}, }, "import non-existing tag": { name: "testis:latest", err: "does not exist on the image stream", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", }, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "nonlatest": {From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:latest"}}, }, }, }, }, "import tag from .spec.tags": { name: "testis:mytag", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", }, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "mytag": { From: &kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:mytag"}, }, }, }, }, expectedImages: []imageapi.ImageImportSpec{{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage:mytag"}, To: &kapi.LocalObjectReference{Name: "mytag"}, }}, }, "import tag from .spec.tags with Kind != DockerImage": { name: "testis:mytag", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", }, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ "mytag": { From: &kapi.ObjectReference{Kind: "ImageStreamTag", Name: "someimage:mytag"}, }, }, }, }, err: "tag \"mytag\" points to existing ImageStreamTag \"someimage:mytag\", it cannot be re-imported", }, "use insecure annotation": { name: "testis", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", Annotations: map[string]string{imageapi.InsecureRepositoryAnnotation: "true"}, }, Spec: imageapi.ImageStreamSpec{ DockerImageRepository: "repo.com/somens/someimage", Tags: make(map[string]imageapi.TagReference), }, }, expectedImages: []imageapi.ImageImportSpec{{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage"}, To: &kapi.LocalObjectReference{Name: "latest"}, ImportPolicy: imageapi.TagImportPolicy{Insecure: true}, }}, }, "insecure flag overrides insecure annotation": { name: "testis", insecure: newBool(false), stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Name: "testis", Namespace: "other", Annotations: map[string]string{imageapi.InsecureRepositoryAnnotation: "true"}, }, Spec: imageapi.ImageStreamSpec{ DockerImageRepository: "repo.com/somens/someimage", Tags: make(map[string]imageapi.TagReference), }, }, expectedImages: []imageapi.ImageImportSpec{{ From: kapi.ObjectReference{Kind: "DockerImage", Name: "repo.com/somens/someimage"}, To: &kapi.LocalObjectReference{Name: "latest"}, ImportPolicy: imageapi.TagImportPolicy{Insecure: false}, }}, }, } for name, test := range testCases { var fake *testclient.Fake if test.stream == nil { fake = testclient.NewSimpleFake() } else { fake = testclient.NewSimpleFake(test.stream) } o := ImportImageOptions{ Target: test.name, From: test.from, All: test.all, Insecure: test.insecure, Confirm: test.confirm, isClient: fake.ImageStreams(""), } // we need to run Validate, because it sets appropriate Name and Tag if err := o.Validate(&cobra.Command{}); err != nil { t.Errorf("%s: unexpected error: %v", name, err) } _, isi, err := o.createImageImport() // check errors if len(test.err) > 0 { if err == nil || !strings.Contains(err.Error(), test.err) { t.Errorf("%s: unexpected error: expected %s, got %v", name, test.err, err) } if isi != nil { t.Errorf("%s: unexpected import spec: expected nil, got %#v", name, isi) } continue } if len(test.err) == 0 && err != nil { t.Errorf("%s: unexpected error: %v", name, err) continue } // check values if !listEqual(isi.Spec.Images, test.expectedImages) { t.Errorf("%s: unexpected import images, expected %#v, got %#v", name, test.expectedImages, isi.Spec.Images) } if !kapi.Semantic.DeepEqual(isi.Spec.Repository, test.expectedRepository) { t.Errorf("%s: unexpected import repository, expected %#v, got %#v", name, test.expectedRepository, isi.Spec.Repository) } } }