package v1alpha1 import ( "sort" "testing" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/version" ) func TestPackageBundle_Find(t *testing.T) { var err error givenBundle := func(versions []SourceVersion) PackageBundle { return PackageBundle{ Spec: PackageBundleSpec{ Packages: []BundlePackage{ { Name: "hello-eks-anywhere", Source: BundlePackageSource{ Registry: "public.ecr.aws/l0g8r8j6", Repository: "hello-eks-anywhere", Versions: versions, }, }, }, }, } } sut := givenBundle( []SourceVersion{ { Name: "0.1.0", Digest: "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7", }, }, ) expected := PackageOCISource{ Registry: "public.ecr.aws/l0g8r8j6", Repository: "hello-eks-anywhere", Digest: "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7", Version: "0.1.0", } actual, err := sut.FindOCISourceByName("hello-eks-anywhere", "0.1.0") assert.NoError(t, err) assert.Equal(t, expected, actual) actual, err = sut.FindOCISourceByName("hello-eks-anywhere", "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7") assert.NoError(t, err) assert.Equal(t, expected, actual) expectedPkgNotFoundErr := "package not found in bundle (fake bundle): Bogus" sut.ObjectMeta.Name = "fake bundle" _, err = sut.FindPackage("Bogus") assert.EqualError(t, err, expectedPkgNotFoundErr) expectedPkgVersionNotFoundErr := "package version not found in bundle (fake bundle): hello-eks-anywhere @ 9.9.9" _, err = sut.FindOCISourceByName("hello-eks-anywhere", "9.9.9") assert.EqualError(t, err, expectedPkgVersionNotFoundErr) t.Run("Get latest version returns the first item", func(t *testing.T) { latest := givenBundle( []SourceVersion{ { Name: "0.1.1", Digest: "sha256:deadbeef", }, { Name: "0.1.0", Digest: "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7", }, }, ) expected := PackageOCISource{ Registry: "public.ecr.aws/l0g8r8j6", Repository: "hello-eks-anywhere", Digest: "sha256:deadbeef", Version: "0.1.1", } actual, err = latest.FindOCISourceByName("hello-eks-anywhere", Latest) assert.NoError(t, err) assert.Equal(t, expected, actual) }) t.Run("Get latest version returns the first item even if the name describes a later version", func(t *testing.T) { latest := givenBundle( []SourceVersion{ { Name: "0.1.0", Digest: "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7", }, { Name: "0.1.1", Digest: "sha256:deadbeef", }, }, ) expected := PackageOCISource{ Registry: "public.ecr.aws/l0g8r8j6", Repository: "hello-eks-anywhere", Digest: "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7", Version: "0.1.0", } actual, err = latest.FindOCISourceByName("hello-eks-anywhere", Latest) assert.NoError(t, err) assert.Equal(t, expected, actual) }) } func TestGetMajorMinorFromString(t *testing.T) { t.Run("Parse from default Kubernetes version name", func(t *testing.T) { targetVersion := "v1-21-1" major, minor := getMajorMinorFromString(targetVersion) assert.Equal(t, 1, major) assert.Equal(t, 21, minor) }) t.Run("Parse from Kubernetes version name without patch number", func( t *testing.T) { targetVersion := "v1-21" major, minor := getMajorMinorFromString(targetVersion) assert.Equal(t, 1, major) assert.Equal(t, 21, minor) }) t.Run("Parse from Kubernetes version name without v perfix", func( t *testing.T) { targetVersion := "1-21-1" major, minor := getMajorMinorFromString(targetVersion) assert.Equal(t, 1, major) assert.Equal(t, 21, minor) }) t.Run("Parse from empty Kubernetes version name", func(t *testing.T) { targetVersion := "" major, minor := getMajorMinorFromString(targetVersion) assert.Equal(t, 0, major) assert.Equal(t, 0, minor) }) } func TestKubeVersionMatches(t *testing.T) { bundle := PackageBundle{ObjectMeta: metav1.ObjectMeta{ Name: "v1-21-1001"}} t.Run("Kubernetes version matches", func(t *testing.T) { var targetVersion = &version.Info{Major: "1", Minor: "21"} result, err := bundle.KubeVersionMatches(targetVersion) assert.True(t, result) assert.NoError(t, err) }) t.Run("Kubernetes major version doesn't match", func(t *testing.T) { var targetVersion = &version.Info{Major: "2", Minor: "21"} result, err := bundle.KubeVersionMatches(targetVersion) assert.False(t, result) assert.NoError(t, err) }) t.Run("Kubernetes minor version doesn't match", func(t *testing.T) { var targetVersion = &version.Info{Major: "1", Minor: "22"} result, err := bundle.KubeVersionMatches(targetVersion) assert.False(t, result) assert.NoError(t, err) }) t.Run("bogus major", func(t *testing.T) { bundle := PackageBundle{ObjectMeta: metav1.ObjectMeta{ Name: "vx-21-1001"}} var targetVersion = &version.Info{Major: "1", Minor: "21"} result, err := bundle.KubeVersionMatches(targetVersion) assert.False(t, result) assert.EqualError(t, err, "invalid major number ") }) t.Run("bogus minor", func(t *testing.T) { bundle := PackageBundle{ObjectMeta: metav1.ObjectMeta{ Name: "v1-x-1001"}} var targetVersion = &version.Info{Major: "1", Minor: "21"} result, err := bundle.KubeVersionMatches(targetVersion) assert.False(t, result) assert.EqualError(t, err, "invalid minor number ") }) t.Run("bogus build", func(t *testing.T) { bundle := PackageBundle{ObjectMeta: metav1.ObjectMeta{ Name: "v1-21-x"}} var targetVersion = &version.Info{Major: "1", Minor: "21"} result, err := bundle.KubeVersionMatches(targetVersion) assert.False(t, result) assert.EqualError(t, err, "invalid build number ") }) } func TestIsValidVersion(t *testing.T) { t.Run("valid version", func(t *testing.T) { bundle := PackageBundle{ObjectMeta: metav1.ObjectMeta{Name: "v1-21-1001"}} assert.True(t, bundle.IsValidVersion()) }) t.Run("invalid version", func(t *testing.T) { bundle := PackageBundle{ObjectMeta: metav1.ObjectMeta{Name: "v1-21-oops"}} assert.False(t, bundle.IsValidVersion()) }) } func TestPackageMatches(t *testing.T) { orig := BundlePackageSource{ Registry: "registry", Repository: "repository", Versions: []SourceVersion{ {Name: "v1", Digest: "sha256:deadbeef"}, {Name: "v2", Digest: "sha256:cafebabe"}, }, } t.Run("package matches", func(t *testing.T) { other := BundlePackageSource{ Registry: "registry", Repository: "repository", Versions: []SourceVersion{ {Name: "v1", Digest: "sha256:deadbeef"}, {Name: "v2", Digest: "sha256:cafebabe"}, }, } result := orig.PackageMatches(other) assert.True(t, result) }) t.Run("package registries must match", func(t *testing.T) { other := BundlePackageSource{ Registry: "registry2", Repository: "repository", Versions: []SourceVersion{ {Name: "v1", Digest: "sha256:deadbeef"}, {Name: "v2", Digest: "sha256:cafebabe"}, }, } result := orig.PackageMatches(other) assert.False(t, result) }) t.Run("package repositories must match", func(t *testing.T) { other := BundlePackageSource{ Registry: "registry", Repository: "repository2", Versions: []SourceVersion{ {Name: "v1", Digest: "sha256:deadbeef"}, {Name: "v2", Digest: "sha256:cafebabe"}, }, } result := orig.PackageMatches(other) assert.False(t, result) }) t.Run("package added versions cause mismatch", func(t *testing.T) { other := BundlePackageSource{ Registry: "registry", Repository: "repository", Versions: []SourceVersion{ {Name: "v1", Digest: "sha256:deadbeef"}, {Name: "v2", Digest: "sha256:cafebabe"}, {Name: "v3", Digest: "sha256:deadf00d"}, }, } result := orig.PackageMatches(other) assert.False(t, result) }) t.Run("package removed versions cause mismatch", func(t *testing.T) { other := BundlePackageSource{ Registry: "registry", Repository: "repository", Versions: []SourceVersion{ {Name: "v2", Digest: "sha256:cafebabe"}, }, } result := orig.PackageMatches(other) assert.False(t, result) }) t.Run("package changed tags cause mismatch", func(t *testing.T) { other := BundlePackageSource{ Registry: "registry", Repository: "repository", Versions: []SourceVersion{ {Name: "v1", Digest: "sha256:feedface"}, {Name: "v2", Digest: "sha256:cafebabe"}, }, } result := orig.PackageMatches(other) assert.False(t, result) }) } func TestSourceVersionKey(t *testing.T) { t.Parallel() s := SourceVersion{ Name: "v1", Digest: "sha256:blah", } t.Run("smoke test", func(t *testing.T) { t.Parallel() assert.Equal(t, s.Key(), "v1 sha256:blah") }) t.Run("includes the name", func(t *testing.T) { t.Parallel() got := s.Key() assert.Contains(t, got, "v1") }) t.Run("includes the tag", func(t *testing.T) { t.Parallel() got := s.Key() assert.Contains(t, got, "sha256:blah") }) } func TestIsNewer(t *testing.T) { t.Parallel() givenBundle := func(name string) PackageBundle { return PackageBundle{ObjectMeta: metav1.ObjectMeta{Name: name}} } t.Run("less than", func(t *testing.T) { t.Parallel() current := givenBundle("v1-21-10002") candidate := givenBundle("v1-21-10003") assert.True(t, current.LessThan(&candidate)) }) t.Run("greater than", func(t *testing.T) { t.Parallel() current := givenBundle("v1-21-10002") candidate := givenBundle("v1-21-10001") assert.False(t, current.LessThan(&candidate)) }) t.Run("equal returns false", func(t *testing.T) { t.Parallel() current := givenBundle("v1-21-10002") candidate := givenBundle("v1-21-10002") assert.False(t, current.LessThan(&candidate)) }) t.Run("newer kube major version", func(t *testing.T) { t.Parallel() current := givenBundle("v1-21-10002") candidate := givenBundle("v2-21-10002") assert.True(t, current.LessThan(&candidate)) }) t.Run("newer kube minor version", func(t *testing.T) { t.Parallel() current := givenBundle("v1-21-10002") candidate := givenBundle("v1-22-10002") assert.True(t, current.LessThan(&candidate)) }) } func TestGetPackageFromBundle(t *testing.T) { givenBundle := func(versions []SourceVersion) PackageBundle { return PackageBundle{ Spec: PackageBundleSpec{ Packages: []BundlePackage{ { Name: "hello-eks-anywhere", Source: BundlePackageSource{ Registry: "public.ecr.aws/l0g8r8j6", Repository: "hello-eks-anywhere", Versions: versions, }, }, }, }, } } t.Run("Get Package from bundle succeeds", func(t *testing.T) { bundle := givenBundle( []SourceVersion{ { Name: "0.1.0", Digest: "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7", }, }, ) result, err := bundle.FindPackage("hello-eks-anywhere") assert.NoError(t, err) assert.Equal(t, bundle.Spec.Packages[0].Name, result.Name) }) t.Run("Get Package from bundle fails", func(t *testing.T) { bundle := givenBundle( []SourceVersion{ { Name: "0.1.0", Digest: "sha256:eaa07ae1c06ffb563fe3c16cdb317f7ac31c8f829d5f1f32442f0e5ab982c3e7", }, }, ) _, err := bundle.FindPackage("harbor") assert.NotNil(t, err) }) } func TestGetJsonSchemFromBundlePackage(t *testing.T) { givenBundle := func(versions []SourceVersion) PackageBundle { return PackageBundle{ Spec: PackageBundleSpec{ Packages: []BundlePackage{ { Name: "hello-eks-anywhere", Source: BundlePackageSource{ Versions: versions, }, }, }, }, } } t.Run("Get json schema from bundle succeeds", func(t *testing.T) { bundle := givenBundle( []SourceVersion{ { Schema: "H4sIAAAAAAAAA5VQvW7DIBDe/RQIdawh9ZgtqjplqZonuOCzTYIBHViRG+XdizGNImWoun7/d9eKMf6iW75lfIjRh62UAxrjajyHGux8GZBQeFBn6DGIhAoY4dtZuASh3CiDGnAEcQrO8tectiKPiQtZF6GjXrYEXZTNptnUb01JWM1RR4PZ+jSiCGafeXc8oYor5sl5pKgxJOaakIQFN5HCL+x1iDTf8YeEhGvb54SMt9jBZOJC+elotBKoSKQz5dOKog+KtI86HZ48h1zIqDSyzhErbxM8e26r9X7jfxbt8s/Zx/7Adn8teXc2grZILDf9tldlAYe21YsWzOfj4zowAatb9QNC+U5rEwIAAA==", }, }, ) expected := "{\n \"$id\": \"https://hello-eks-anywhere.packages.eks.amazonaws.com/schema.json\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"title\": \"hello-eks-anywhere\",\n \"type\": \"object\",\n \"properties\": {\n \"sourceRegistry\": {\n \"type\": \"string\",\n \"default\": \"public.ecr.aws/eks-anywhere\",\n \"description\": \"Source registry for package.\"\n },\n \"title\": {\n \"type\": \"string\",\n \"default\": \"Amazon EKS Anywhere\",\n \"description\": \"Container title.\"\n }\n },\n \"additionalProperties\": false\n}\n" packageBundle := bundle.Spec.Packages[0] version := packageBundle.Source.Versions[0] schema, err := packageBundle.GetJsonSchema(&version) assert.NoError(t, err) assert.Equal(t, expected, string(schema)) }) t.Run("Get json schema from bundle fails when not compressed", func(t *testing.T) { bundle := givenBundle( []SourceVersion{ { Schema: "ewogICIkaWQiOiAiaHR0cHM6Ly9oZWxsby1la3MtYW55d2hlcmUucGFja2FnZXMuZWtzLmFtYXpvbmF3cy5jb20vc2NoZW1hLmpzb24iLAogICIkc2NoZW1hIjogImh0dHBzOi8vanNvbi1zY2hlbWEub3JnL2RyYWZ0LzIwMjAtMTIvc2NoZW1hIiwKICAidGl0bGUiOiAiaGVsbG8tZWtzLWFueXdoZXJlIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInNvdXJjZVJlZ2lzdHJ5IjogewogICAgICAidHlwZSI6ICJzdHJpbmciLAogICAgICAiZGVmYXVsdCI6ICJwdWJsaWMuZWNyLmF3cy9la3MtYW55d2hlcmUiLAogICAgICAiZGVzY3JpcHRpb24iOiAiU291cmNlIHJlZ2lzdHJ5IGZvciBwYWNrYWdlLiIKICAgIH0sCiAgICAidGl0bGUiOiB7CiAgICAgICJ0eXBlIjogInN0cmluZyIsCiAgICAgICJkZWZhdWx0IjogIkFtYXpvbiBFS1MgQW55d2hlcmUiLAogICAgICAiZGVzY3JpcHRpb24iOiAiQ29udGFpbmVyIHRpdGxlLiIKICAgIH0KICB9LAp9Cg==", }, }, ) packageBundle := bundle.Spec.Packages[0] version := packageBundle.Source.Versions[0] _, err := packageBundle.GetJsonSchema(&version) assert.NotNil(t, err) }) } func TestBundlesByVersion(t *testing.T) { t.Run("sort.Interface is implemented", func(t *testing.T) { bundles := []PackageBundle{ {ObjectMeta: metav1.ObjectMeta{Name: "v1-21-003"}}, {ObjectMeta: metav1.ObjectMeta{Name: "v1-21-001"}}, {ObjectMeta: metav1.ObjectMeta{Name: "v1-21-002"}}, } sort.Sort(BundlesByVersion(bundles)) assert.Equal(t, bundles[0].Name, "v1-21-001") assert.Equal(t, bundles[1].Name, "v1-21-002") assert.Equal(t, bundles[2].Name, "v1-21-003") }) }