package cmd import ( "strings" "testing" "github.com/spf13/cobra" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" "github.com/openshift/origin/pkg/client/testclient" imageapi "github.com/openshift/origin/pkg/image/api" ) 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 from .spec.dockerImageRepository non-existing tag": { name: "testis:nonexisting", stream: &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: "testis", Namespace: "other"}, Spec: imageapi.ImageStreamSpec{ DockerImageRepository: "repo.com/somens/someimage", Tags: make(map[string]imageapi.TagReference), }, }, err: `"nonexisting" does not exist on the image stream`, }, "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) } } } func TestWasError(t *testing.T) { testCases := map[string]struct { isi *imageapi.ImageStreamImport expected bool }{ "no error": { isi: &imageapi.ImageStreamImport{}, expected: false, }, "error importing images": { isi: &imageapi.ImageStreamImport{ Status: imageapi.ImageStreamImportStatus{ Images: []imageapi.ImageImportStatus{ {Status: unversioned.Status{Status: unversioned.StatusFailure}}, }, }, }, expected: true, }, "error importing repository": { isi: &imageapi.ImageStreamImport{ Status: imageapi.ImageStreamImportStatus{ Repository: &imageapi.RepositoryImportStatus{ Status: unversioned.Status{Status: unversioned.StatusFailure}, }, }, }, expected: true, }, } for name, test := range testCases { if a, e := wasError(test.isi), test.expected; a != e { t.Errorf("%s: expected %v, got %v", name, e, a) } } } func listEqual(actual, expected []imageapi.ImageImportSpec) bool { if len(actual) != len(expected) { return false } for _, a := range actual { found := false for _, e := range expected { if kapi.Semantic.DeepEqual(a, e) { found = true break } } if !found { return false } } return true } func newBool(a bool) *bool { r := new(bool) *r = a return r }