package image import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" "github.com/argoproj-labs/argocd-image-updater/registry-scanner/pkg/tag" ) func Test_ParseImageTags(t *testing.T) { t.Run("Parse valid image name without registry info", func(t *testing.T) { image := NewFromIdentifier("jannfis/test-image:0.1") assert.Empty(t, image.RegistryURL) assert.Empty(t, image.ImageAlias) assert.Equal(t, "jannfis/test-image", image.ImageName) require.NotNil(t, image.ImageTag) assert.Equal(t, "0.1", image.ImageTag.TagName) assert.Equal(t, "jannfis/test-image:0.1", image.GetFullNameWithTag()) assert.Equal(t, "jannfis/test-image", image.GetFullNameWithoutTag()) }) t.Run("Single element image name is unmodified", func(t *testing.T) { image := NewFromIdentifier("test-image") assert.Empty(t, image.RegistryURL) assert.Empty(t, image.ImageAlias) assert.Equal(t, "test-image", image.ImageName) require.Nil(t, image.ImageTag) assert.Equal(t, "test-image", image.GetFullNameWithTag()) assert.Equal(t, "test-image", image.GetFullNameWithoutTag()) }) t.Run("library image name is unmodified", func(t *testing.T) { image := NewFromIdentifier("library/test-image") assert.Empty(t, image.RegistryURL) assert.Empty(t, image.ImageAlias) assert.Equal(t, "library/test-image", image.ImageName) require.Nil(t, image.ImageTag) assert.Equal(t, "library/test-image", image.GetFullNameWithTag()) assert.Equal(t, "library/test-image", image.GetFullNameWithoutTag()) }) t.Run("Parse valid image name with registry info", func(t *testing.T) { image := NewFromIdentifier("gcr.io/jannfis/test-image:0.1") assert.Equal(t, "gcr.io", image.RegistryURL) assert.Empty(t, image.ImageAlias) assert.Equal(t, "jannfis/test-image", image.ImageName) require.NotNil(t, image.ImageTag) assert.Equal(t, "0.1", image.ImageTag.TagName) assert.Equal(t, "gcr.io/jannfis/test-image:0.1", image.GetFullNameWithTag()) assert.Equal(t, "gcr.io/jannfis/test-image", image.GetFullNameWithoutTag()) }) t.Run("Parse valid image name with default registry info", func(t *testing.T) { image := NewFromIdentifier("docker.io/jannfis/test-image:0.1") assert.Equal(t, "docker.io", image.RegistryURL) assert.Empty(t, image.ImageAlias) assert.Equal(t, "jannfis/test-image", image.ImageName) require.NotNil(t, image.ImageTag) assert.Equal(t, "0.1", image.ImageTag.TagName) assert.Equal(t, "docker.io/jannfis/test-image:0.1", image.GetFullNameWithTag()) assert.Equal(t, "docker.io/jannfis/test-image", image.GetFullNameWithoutTag()) }) t.Run("Parse valid image name with digest tag", func(t *testing.T) { image := NewFromIdentifier("gcr.io/jannfis/test-image@sha256:abcde") assert.Equal(t, "gcr.io", image.RegistryURL) assert.Empty(t, image.ImageAlias) assert.Equal(t, "jannfis/test-image", image.ImageName) require.NotNil(t, image.ImageTag) assert.Empty(t, image.ImageTag.TagName) assert.Equal(t, "sha256:abcde", image.ImageTag.TagDigest) assert.Equal(t, "latest@sha256:abcde", image.GetTagWithDigest()) assert.Equal(t, "gcr.io/jannfis/test-image@sha256:abcde", image.GetFullNameWithTag()) assert.Equal(t, "gcr.io/jannfis/test-image", image.GetFullNameWithoutTag()) }) t.Run("Parse valid image name with tag and digest", func(t *testing.T) { image := NewFromIdentifier("gcr.io/jannfis/test-image:test-tag@sha256:abcde") require.NotNil(t, image.ImageTag) assert.Equal(t, "test-tag", image.ImageTag.TagName) assert.Equal(t, "sha256:abcde", image.ImageTag.TagDigest) assert.Equal(t, "test-tag@sha256:abcde", image.GetTagWithDigest()) assert.Equal(t, "gcr.io/jannfis/test-image", image.GetFullNameWithoutTag()) assert.Equal(t, "gcr.io/jannfis/test-image:test-tag@sha256:abcde", image.GetFullNameWithTag()) }) t.Run("Parse valid image name with source name and registry info", func(t *testing.T) { image := NewFromIdentifier("jannfis/orig-image=gcr.io/jannfis/test-image:0.1") assert.Equal(t, "gcr.io", image.RegistryURL) assert.Equal(t, "jannfis/orig-image", image.ImageAlias) assert.Equal(t, "jannfis/test-image", image.ImageName) require.NotNil(t, image.ImageTag) assert.Equal(t, "0.1", image.ImageTag.TagName) }) t.Run("Parse valid image name with source name and registry info with port", func(t *testing.T) { image := NewFromIdentifier("ghcr.io:4567/jannfis/orig-image=gcr.io:1234/jannfis/test-image:0.1") assert.Equal(t, "gcr.io:1234", image.RegistryURL) assert.Equal(t, "ghcr.io:4567/jannfis/orig-image", image.ImageAlias) assert.Equal(t, "jannfis/test-image", image.ImageName) require.NotNil(t, image.ImageTag) assert.Equal(t, "0.1", image.ImageTag.TagName) }) t.Run("Parse image without version source name and registry info", func(t *testing.T) { image := NewFromIdentifier("jannfis/orig-image=gcr.io/jannfis/test-image") assert.Equal(t, "gcr.io", image.RegistryURL) assert.Equal(t, "jannfis/orig-image", image.ImageAlias) assert.Equal(t, "jannfis/test-image", image.ImageName) assert.Nil(t, image.ImageTag) }) t.Run("#273 classic-web=registry:5000/classic-web", func(t *testing.T) { image := NewFromIdentifier("classic-web=registry:5000/classic-web") assert.Equal(t, "registry:5000", image.RegistryURL) assert.Equal(t, "classic-web", image.ImageAlias) assert.Equal(t, "classic-web", image.ImageName) assert.Nil(t, image.ImageTag) }) } func Test_ImageToString(t *testing.T) { t.Run("Get string representation of full-qualified image name", func(t *testing.T) { imageName := "jannfis/argocd=jannfis/orig-image:0.1" img := NewFromIdentifier(imageName) assert.Equal(t, imageName, img.String()) }) t.Run("Get string representation of full-qualified image name with registry", func(t *testing.T) { imageName := "jannfis/argocd=gcr.io/jannfis/orig-image:0.1" img := NewFromIdentifier(imageName) assert.Equal(t, imageName, img.String()) }) t.Run("Get string representation of full-qualified image name with registry", func(t *testing.T) { imageName := "jannfis/argocd=gcr.io/jannfis/orig-image" img := NewFromIdentifier(imageName) assert.Equal(t, imageName, img.String()) }) t.Run("Get original value", func(t *testing.T) { imageName := "invalid==foo" img := NewFromIdentifier(imageName) assert.Equal(t, imageName, img.Original()) }) } func Test_WithTag(t *testing.T) { t.Run("Get string representation of full-qualified image name", func(t *testing.T) { imageName := "jannfis/argocd=jannfis/orig-image:0.1" nimageName := "jannfis/argocd=jannfis/orig-image:0.2" oImg := NewFromIdentifier(imageName) nImg := oImg.WithTag(tag.NewImageTag("0.2", time.Unix(0, 0), "")) assert.Equal(t, nimageName, nImg.String()) }) } func Test_ContainerList(t *testing.T) { t.Run("Test whether image is contained in list", func(t *testing.T) { images := make(ContainerImageList, 0) image_names := []string{"a/a:0.1", "a/b:1.2", "x/y=foo.bar/a/c:0.23"} for _, n := range image_names { images = append(images, NewFromIdentifier(n)) } withKustomizeOverride := NewFromIdentifier("k1/k2:k3") withKustomizeOverride.KustomizeImage = images[0] images = append(images, withKustomizeOverride) assert.NotNil(t, images.ContainsImage(NewFromIdentifier(image_names[0]), false)) assert.NotNil(t, images.ContainsImage(NewFromIdentifier(image_names[1]), false)) assert.NotNil(t, images.ContainsImage(NewFromIdentifier(image_names[2]), false)) assert.Nil(t, images.ContainsImage(NewFromIdentifier("foo/bar"), false)) imageMatch := images.ContainsImage(withKustomizeOverride, false) assert.Equal(t, images[0], imageMatch) }) } func Test_getImageDigestFromTag(t *testing.T) { tagAndDigest := "test-tag@sha256:abcde" tagName, tagDigest := getImageDigestFromTag(tagAndDigest) assert.Equal(t, "test-tag", tagName) assert.Equal(t, "sha256:abcde", tagDigest) tagAndDigest = "test-tag" tagName, tagDigest = getImageDigestFromTag(tagAndDigest) assert.Equal(t, "test-tag", tagName) assert.Empty(t, tagDigest) } func Test_ContainerImageList_String_Originals(t *testing.T) { images := make(ContainerImageList, 0) originals := []string{} assert.Equal(t, "", images.String()) assert.True(t, slices.Equal(originals, images.Originals())) images = append(images, NewFromIdentifier("foo/bar:0.1")) originals = append(originals, "foo/bar:0.1") assert.Equal(t, "foo/bar:0.1", images.String()) assert.True(t, slices.Equal(originals, images.Originals())) images = append(images, NewFromIdentifier("alias=foo/bar:0.2")) originals = append(originals, "alias=foo/bar:0.2") assert.Equal(t, "foo/bar:0.1,alias=foo/bar:0.2", images.String()) assert.True(t, slices.Equal(originals, images.Originals())) } func TestContainerImage_DiffersFrom(t *testing.T) { foo1 := NewFromIdentifier("x/foo:1") foo2 := NewFromIdentifier("x/foo:2") bar1 := NewFromIdentifier("x/bar:1") bar1WithRegistry := NewFromIdentifier("docker.io/x/bar:1") assert.False(t, foo1.DiffersFrom(foo1, true)) assert.False(t, foo1.DiffersFrom(foo2, false)) assert.True(t, foo1.DiffersFrom(foo2, true)) assert.True(t, foo1.DiffersFrom(bar1, false)) assert.True(t, bar1.DiffersFrom(foo1, false)) assert.True(t, foo1.DiffersFrom(bar1, true)) assert.True(t, bar1.DiffersFrom(foo1, true)) assert.True(t, bar1.DiffersFrom(bar1WithRegistry, false)) assert.False(t, foo1.IsUpdatable("0.1", "^1.0")) }