diff --git a/pkg/package-server/provider/registry.go b/pkg/package-server/provider/registry.go index 456546e4e3..ff0b1075a6 100644 --- a/pkg/package-server/provider/registry.go +++ b/pkg/package-server/provider/registry.go @@ -412,7 +412,7 @@ func (p *RegistryProvider) Get(namespace, name string) (*operators.PackageManife func (p *RegistryProvider) List(namespace string, selector labels.Selector) (*operators.PackageManifestList, error) { var pkgs []*operators.PackageManifest if namespace == metav1.NamespaceAll { - all, err := p.pkgLister.List(labels.Everything()) + all, err := p.pkgLister.List(selector) if err != nil { return nil, err } diff --git a/pkg/package-server/provider/registry_test.go b/pkg/package-server/provider/registry_test.go index 00528633f4..c5a38ef513 100644 --- a/pkg/package-server/provider/registry_test.go +++ b/pkg/package-server/provider/registry_test.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "io" + "k8s.io/apimachinery/pkg/selection" "net" "os" "path/filepath" @@ -1076,6 +1077,316 @@ func TestRegistryProviderList(t *testing.T) { } } +type LabelReq struct { + key string + op selection.Operator + strValues []string +} + +func TestRegistryProviderListLabels(t *testing.T) { + tests := []struct { + name string + globalNS string + labelReq *LabelReq + registryClients []*registryClient + requestNamespace string + expectedErr string + expected *operators.PackageManifestList + }{ + { + name: "PackagesFound/LabelsSupported/SingleNS", + globalNS: "ns", + labelReq: &LabelReq{ + key: "catalog", + op: selection.Exists, + }, + registryClients: []*registryClient{ + newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", "ns"), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))), + }, + requestNamespace: "ns", + expectedErr: "", + expected: &operators.PackageManifestList{Items: []operators.PackageManifest{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "prometheus", + Namespace: "ns", + Labels: labels.Set{ + "catalog": "cool-operators", + "catalog-namespace": "ns", + "provider": "Red Hat", + "provider-url": "", + "operatorframework.io/arch.amd64": "supported", + "operatorframework.io/os.linux": "supported", + }, + }, + Status: operators.PackageManifestStatus{ + CatalogSource: "cool-operators", + CatalogSourceNamespace: "ns", + PackageName: "prometheus", + Provider: operators.AppLink{ + Name: "Red Hat", + }, + DefaultChannel: "preview", + Channels: []operators.PackageChannel{ + { + Name: "preview", + CurrentCSV: "prometheusoperator.0.22.2", + CurrentCSVDesc: func() operators.CSVDescription { + csv := operatorsv1alpha1.ClusterServiceVersion{} + require.NoError(t, json.Unmarshal([]byte(prometheusCSVJSON), &csv)) + return operators.CreateCSVDescription(&csv) + }(), + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "etcd", + Namespace: "ns", + Labels: labels.Set{ + "catalog": "cool-operators", + "catalog-namespace": "ns", + "provider": "CoreOS, Inc", + "provider-url": "", + "operatorframework.io/arch.amd64": "supported", + "operatorframework.io/os.linux": "supported", + }, + }, + Status: operators.PackageManifestStatus{ + CatalogSource: "cool-operators", + CatalogSourceNamespace: "ns", + PackageName: "etcd", + Provider: operators.AppLink{ + Name: "CoreOS, Inc", + }, + DefaultChannel: "alpha", + Channels: []operators.PackageChannel{ + { + Name: "alpha", + CurrentCSV: "etcdoperator.v0.9.2", + CurrentCSVDesc: func() operators.CSVDescription { + csv := operatorsv1alpha1.ClusterServiceVersion{} + require.NoError(t, json.Unmarshal([]byte(etcdCSVJSON), &csv)) + return operators.CreateCSVDescription(&csv) + }(), + }, + }, + }, + }, + }}, + }, + { + name: "PackagesFound/LabelsSupported/GlobalNS", + globalNS: "ns", + labelReq: &LabelReq{ + key: "catalog", + op: selection.Exists, + }, + registryClients: []*registryClient{ + newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", "ns"), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))), + }, + requestNamespace: "", + expectedErr: "", + expected: &operators.PackageManifestList{Items: []operators.PackageManifest{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "prometheus", + Namespace: "ns", + Labels: labels.Set{ + "catalog": "cool-operators", + "catalog-namespace": "ns", + "provider": "Red Hat", + "provider-url": "", + "operatorframework.io/arch.amd64": "supported", + "operatorframework.io/os.linux": "supported", + }, + }, + Status: operators.PackageManifestStatus{ + CatalogSource: "cool-operators", + CatalogSourceNamespace: "ns", + PackageName: "prometheus", + Provider: operators.AppLink{ + Name: "Red Hat", + }, + DefaultChannel: "preview", + Channels: []operators.PackageChannel{ + { + Name: "preview", + CurrentCSV: "prometheusoperator.0.22.2", + CurrentCSVDesc: func() operators.CSVDescription { + csv := operatorsv1alpha1.ClusterServiceVersion{} + require.NoError(t, json.Unmarshal([]byte(prometheusCSVJSON), &csv)) + return operators.CreateCSVDescription(&csv) + }(), + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "etcd", + Namespace: "ns", + Labels: labels.Set{ + "catalog": "cool-operators", + "catalog-namespace": "ns", + "provider": "CoreOS, Inc", + "provider-url": "", + "operatorframework.io/arch.amd64": "supported", + "operatorframework.io/os.linux": "supported", + }, + }, + Status: operators.PackageManifestStatus{ + CatalogSource: "cool-operators", + CatalogSourceNamespace: "ns", + PackageName: "etcd", + Provider: operators.AppLink{ + Name: "CoreOS, Inc", + }, + DefaultChannel: "alpha", + Channels: []operators.PackageChannel{ + { + Name: "alpha", + CurrentCSV: "etcdoperator.v0.9.2", + CurrentCSVDesc: func() operators.CSVDescription { + csv := operatorsv1alpha1.ClusterServiceVersion{} + require.NoError(t, json.Unmarshal([]byte(etcdCSVJSON), &csv)) + return operators.CreateCSVDescription(&csv) + }(), + }, + }, + }, + }, + }}, + }, + { + name: "PackagesNotFound/LabelsNotSupported/GlobalNS", + globalNS: "", + labelReq: &LabelReq{ + key: "catalog", + op: selection.DoesNotExist, + }, + registryClients: []*registryClient{ + newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", ""), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))), + }, + requestNamespace: "", + expectedErr: "", + expected: &operators.PackageManifestList{Items: []operators.PackageManifest{}}, + }, + { + name: "PackagesFound/LabelsNotProvided/GlobalNS", + globalNS: "", + registryClients: []*registryClient{ + newTestRegistryClient(t, withRegistryServiceStatus(catalogSource("cool-operators", "ns"), "grpc", "cool-operators", "ns", port, metav1.NewTime(time.Now()))), + }, + requestNamespace: "", + expectedErr: "", + expected: &operators.PackageManifestList{Items: []operators.PackageManifest{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "prometheus", + Namespace: "ns", + Labels: labels.Set{ + "catalog": "cool-operators", + "catalog-namespace": "ns", + "provider": "Red Hat", + "provider-url": "", + "operatorframework.io/arch.amd64": "supported", + "operatorframework.io/os.linux": "supported", + }, + }, + Status: operators.PackageManifestStatus{ + CatalogSource: "cool-operators", + CatalogSourceNamespace: "ns", + PackageName: "prometheus", + Provider: operators.AppLink{ + Name: "Red Hat", + }, + DefaultChannel: "preview", + Channels: []operators.PackageChannel{ + { + Name: "preview", + CurrentCSV: "prometheusoperator.0.22.2", + CurrentCSVDesc: func() operators.CSVDescription { + csv := operatorsv1alpha1.ClusterServiceVersion{} + require.NoError(t, json.Unmarshal([]byte(prometheusCSVJSON), &csv)) + return operators.CreateCSVDescription(&csv) + }(), + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "etcd", + Namespace: "ns", + Labels: labels.Set{ + "catalog": "cool-operators", + "catalog-namespace": "ns", + "provider": "CoreOS, Inc", + "provider-url": "", + "operatorframework.io/arch.amd64": "supported", + "operatorframework.io/os.linux": "supported", + }, + }, + Status: operators.PackageManifestStatus{ + CatalogSource: "cool-operators", + CatalogSourceNamespace: "ns", + PackageName: "etcd", + Provider: operators.AppLink{ + Name: "CoreOS, Inc", + }, + DefaultChannel: "alpha", + Channels: []operators.PackageChannel{ + { + Name: "alpha", + CurrentCSV: "etcdoperator.v0.9.2", + CurrentCSVDesc: func() operators.CSVDescription { + csv := operatorsv1alpha1.ClusterServiceVersion{} + require.NoError(t, json.Unmarshal([]byte(etcdCSVJSON), &csv)) + return operators.CreateCSVDescription(&csv) + }(), + }, + }, + }, + }, + }}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + lab := labels.NewSelector() + if test.labelReq != nil { + req, err := labels.NewRequirement(test.labelReq.key, test.labelReq.op, test.labelReq.strValues) + require.NoError(t, err) + lab = lab.Add(*req) + } + + provider, err := NewFakeRegistryProvider(ctx, nil, nil, test.globalNS) + require.NoError(t, err) + + for _, c := range test.registryClients { + require.NoError(t, provider.refreshCache(ctx, c)) + } + + packageManifestList, err := provider.List(test.requestNamespace, lab) + if test.expectedErr != "" { + require.NotNil(t, err) + require.Equal(t, test.expectedErr, err.Error()) + } else { + require.Nil(t, err) + } + + require.Equal(t, len(test.expected.Items), len(packageManifestList.Items)) + require.ElementsMatch(t, test.expected.Items, packageManifestList.Items) + }) + } +} + func newTestRegistryClient(t *testing.T, catsrc *operatorsv1alpha1.CatalogSource) *registryClient { conn, err := grpc.Dial(address+catsrc.Status.RegistryServiceStatus.Port, grpc.WithInsecure()) require.NoError(t, err, "could not set up test grpc connection")