diff --git a/pkg/image/registry/imagerepositorymapping/rest.go b/pkg/image/registry/imagerepositorymapping/rest.go index e3ee25670245..00de63e1a01b 100644 --- a/pkg/image/registry/imagerepositorymapping/rest.go +++ b/pkg/image/registry/imagerepositorymapping/rest.go @@ -59,7 +59,7 @@ func (s *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err } repo.Tags[mapping.Tag] = image.Name - if err := s.imageRegistry.CreateImage(ctx, &image); err != nil { + if err := s.imageRegistry.CreateImage(ctx, &image); err != nil && !errors.IsAlreadyExists(err) { return nil, err } if err := s.imageRepositoryRegistry.UpdateImageRepository(ctx, repo); err != nil { diff --git a/pkg/image/registry/imagerepositorymapping/rest_test.go b/pkg/image/registry/imagerepositorymapping/rest_test.go index 209c626a3e33..ce1f4057ba75 100644 --- a/pkg/image/registry/imagerepositorymapping/rest_test.go +++ b/pkg/image/registry/imagerepositorymapping/rest_test.go @@ -206,3 +206,149 @@ func checkExpectedNamespaceError(t *testing.T, err error) { } } + +func TestAddExistingImageWithNewTag(t *testing.T) { + imageRegistry := test.NewImageRegistry() + imageRegistry.Err = errors.NewAlreadyExists("image", "existingImage") + + imageRepositoryRegistry := test.NewImageRepositoryRegistry() + imageRepositoryRegistry.ImageRepositories = &api.ImageRepositoryList{ + Items: []api.ImageRepository{ + { + ObjectMeta: kapi.ObjectMeta{ + Name: "repo1", + }, + DockerImageRepository: "localhost:5000/someproject/somerepo", + Tags: map[string]string{ + "existingTag": "existingImage", + }, + }, + }, + } + storage := &REST{imageRegistry, imageRepositoryRegistry} + + mapping := api.ImageRepositoryMapping{ + DockerImageRepository: "localhost:5000/someproject/somerepo", + Image: api.Image{ + ObjectMeta: kapi.ObjectMeta{ + Name: "existingImage", + }, + DockerImageReference: "localhost:5000/someproject/somerepo:imageID1", + DockerImageMetadata: api.DockerImage{ + Config: api.DockerConfig{ + Cmd: []string{"ls", "/"}, + Env: []string{"a=1"}, + ExposedPorts: map[string]struct{}{"1234/tcp": {}}, + Memory: 1234, + CPUShares: 99, + WorkingDir: "/workingDir", + }, + }, + }, + Tag: "latest", + } + _, err := storage.Create(kapi.NewDefaultContext(), &mapping) + if err != nil { + t.Errorf("Unexpected error creating mapping: %#v", err) + } + + imageRegistry.Err = nil + + image, err := imageRegistry.GetImage(kapi.NewDefaultContext(), "existingImage") + if err != nil { + t.Errorf("Unexpected error retrieving image: %#v", err) + } + if e, a := mapping.Image.DockerImageReference, image.DockerImageReference; e != a { + t.Errorf("Expected %s, got %s", e, a) + } + if !reflect.DeepEqual(mapping.Image.DockerImageMetadata, image.DockerImageMetadata) { + t.Errorf("Expected %#v, got %#v", mapping.Image, image) + } + + repo, err := imageRepositoryRegistry.GetImageRepository(kapi.NewDefaultContext(), "repo1") + if err != nil { + t.Errorf("Unexpected non-nil err: %#v", err) + } + if repo == nil { + t.Fatalf("Unexpected nil repo") + } + if len(repo.Tags) != 2 { + t.Errorf("Expected 2 tags in repo, got: %v", repo.Tags) + } + if e, a := "existingImage", repo.Tags["existingTag"]; e != a { + t.Errorf("Expected %s, got %s", e, a) + } + if e, a := "existingImage", repo.Tags["latest"]; e != a { + t.Errorf("Expected %s, got %s", e, a) + } +} + +func TestAddExistingImageAndTag(t *testing.T) { + imageRegistry := test.NewImageRegistry() + imageRegistry.Err = errors.NewAlreadyExists("image", "existingImage") + + imageRepositoryRegistry := test.NewImageRepositoryRegistry() + imageRepositoryRegistry.ImageRepositories = &api.ImageRepositoryList{ + Items: []api.ImageRepository{ + { + ObjectMeta: kapi.ObjectMeta{ + Name: "repo1", + }, + DockerImageRepository: "localhost:5000/someproject/somerepo", + Tags: map[string]string{ + "existingTag": "existingImage", + }, + }, + }, + } + storage := &REST{imageRegistry, imageRepositoryRegistry} + + mapping := api.ImageRepositoryMapping{ + DockerImageRepository: "localhost:5000/someproject/somerepo", + Image: api.Image{ + ObjectMeta: kapi.ObjectMeta{ + Name: "existingImage", + }, + DockerImageReference: "localhost:5000/someproject/somerepo:imageID1", + DockerImageMetadata: api.DockerImage{ + Config: api.DockerConfig{ + Cmd: []string{"ls", "/"}, + Env: []string{"a=1"}, + ExposedPorts: map[string]struct{}{"1234/tcp": {}}, + Memory: 1234, + CPUShares: 99, + WorkingDir: "/workingDir", + }, + }, + }, + Tag: "existingTag", + } + _, err := storage.Create(kapi.NewDefaultContext(), &mapping) + if err != nil { + t.Errorf("Unexpected error creating mapping: %#v", err) + } + + imageRegistry.Err = nil + + image, err := imageRegistry.GetImage(kapi.NewDefaultContext(), "existingImage") + if err != nil { + t.Errorf("Unexpected error retrieving image: %#v", err) + } + if e, a := mapping.Image.DockerImageReference, image.DockerImageReference; e != a { + t.Errorf("Expected %s, got %s", e, a) + } + if !reflect.DeepEqual(mapping.Image.DockerImageMetadata, image.DockerImageMetadata) { + t.Errorf("Expected %#v, got %#v", mapping.Image, image) + } + + repo, err := imageRepositoryRegistry.GetImageRepository(kapi.NewDefaultContext(), "repo1") + if err != nil { + t.Errorf("Unexpected non-nil err: %#v", err) + } + if repo == nil { + t.Fatalf("Unexpected nil repo") + } + if e, a := "existingImage", repo.Tags["existingTag"]; e != a { + t.Errorf("Expected %s, got %s", e, a) + } +} diff --git a/test/integration/imageclient_test.go b/test/integration/imageclient_test.go index d5b8670d2059..644a22c5848f 100644 --- a/test/integration/imageclient_test.go +++ b/test/integration/imageclient_test.go @@ -148,8 +148,15 @@ func TestImageRepositoryMappingCreate(t *testing.T) { Image: *image, } mapping.Image.DockerImageReference = "different" - if err := openshift.Client.ImageRepositoryMappings(testNamespace).Create(mapping); err == nil || !errors.IsAlreadyExists(err) { - t.Fatalf("unexpected non-error or type: %v", err) + if err := openshift.Client.ImageRepositoryMappings(testNamespace).Create(mapping); err != nil { + t.Fatalf("unexpected error: %v", err) + } + image, err = openshift.Client.Images(testNamespace).Get(image.Name) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if image.DockerImageReference != "some/other/name" { + t.Fatalf("image was unexpectedly mutated: %#v", image) } // ensure the correct tags are set @@ -157,7 +164,7 @@ func TestImageRepositoryMappingCreate(t *testing.T) { if err != nil { t.Fatalf("Unexpected error: %v", err) } - if !reflect.DeepEqual(updated.Tags, map[string]string{"newer": "image1"}) { + if !reflect.DeepEqual(updated.Tags, map[string]string{"newer": "image1", "newest": "image2"}) { t.Errorf("unexpected object: %#v", updated.Tags) } @@ -168,6 +175,56 @@ func TestImageRepositoryMappingCreate(t *testing.T) { if fromTag.Name != "image1" || fromTag.UID == "" || fromTag.DockerImageReference != "some/other/name" { t.Errorf("unexpected object: %#v", fromTag) } + + fromTag, err = openshift.Client.ImageRepositoryTags(testNamespace).Get(repo.Name, "newest") + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if fromTag.Name != "image2" || fromTag.UID == "" || fromTag.DockerImageReference != "some/other/name" { + t.Errorf("unexpected object: %#v", fromTag) + } + + // verify that image repository mappings can use the same image for different tags + mapping = &imageapi.ImageRepositoryMapping{ + ObjectMeta: kapi.ObjectMeta{Name: repo.Name}, + Tag: "anothertag", + Image: *image, + } + if err := openshift.Client.ImageRepositoryMappings(testNamespace).Create(mapping); err != nil { + t.Fatalf("unexpected error: %v", err) + } + // ensure the correct tags are set + updated, err = openshift.Client.ImageRepositories(testNamespace).Get(repo.Name) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if !reflect.DeepEqual(updated.Tags, map[string]string{"newer": "image1", "newest": "image2", "anothertag": "image2"}) { + t.Errorf("unexpected object: %#v", updated.Tags) + } + + fromTag, err = openshift.Client.ImageRepositoryTags(testNamespace).Get(repo.Name, "newer") + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if fromTag.Name != "image1" || fromTag.UID == "" || fromTag.DockerImageReference != "some/other/name" { + t.Errorf("unexpected object: %#v", fromTag) + } + + fromTag, err = openshift.Client.ImageRepositoryTags(testNamespace).Get(repo.Name, "newest") + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if fromTag.Name != "image2" || fromTag.UID == "" || fromTag.DockerImageReference != "some/other/name" { + t.Errorf("unexpected object: %#v", fromTag) + } + fromTag, err = openshift.Client.ImageRepositoryTags(testNamespace).Get(repo.Name, "anothertag") + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if fromTag.Name != "image2" || fromTag.UID == "" || fromTag.DockerImageReference != "some/other/name" { + t.Errorf("unexpected object: %#v", fromTag) + } + } func TestImageRepositoryDelete(t *testing.T) {