Skip to content

Commit 8ce2896

Browse files
committed
linter fixes
Signed-off-by: Ankita Thomas <[email protected]>
1 parent 74a92f7 commit 8ce2896

File tree

6 files changed

+156
-95
lines changed

6 files changed

+156
-95
lines changed

internal/cmd/internal/olmv1/catalog_search.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@ package olmv1
33
import (
44
"os"
55

6+
"github.com/spf13/cobra"
7+
"github.com/spf13/pflag"
8+
69
"github.com/operator-framework/kubectl-operator/internal/cmd/internal/log"
710
v1action "github.com/operator-framework/kubectl-operator/internal/pkg/v1/action"
811
"github.com/operator-framework/kubectl-operator/pkg/action"
9-
"github.com/spf13/cobra"
10-
"github.com/spf13/pflag"
1112
)
1213

13-
// NewCatalogInstalledGetCmd handles get commands in the form of:
14-
// catalog(s) [catalog_name] - this will either list all the installed operators
15-
// if no catalog_name has been provided or display the details of the specific
16-
// one otherwise
14+
// NewCatalogSearchCmd handles get commands in the form of:
15+
// catalog(s) - this will either list all packages
16+
// from available catalogs if no catalog has been provided.
17+
// The results are restricted to only the contents of specific
18+
// catalogs if either specified by name or label selector.
19+
// results may also be restricted to the contents of a single
20+
// package by name across one or more catalogs.
1721
func NewCatalogSearchCmd(cfg *action.Configuration) *cobra.Command {
1822
i := v1action.NewCatalogSearch(cfg)
1923
i.Logf = log.Printf
@@ -46,7 +50,7 @@ func NewCatalogSearchCmd(cfg *action.Configuration) *cobra.Command {
4650
}
4751

4852
func bindCatalogSearchFlags(fs *pflag.FlagSet, i *v1action.CatalogSearch) {
49-
fs.StringVar(&i.Catalog, "catalog", "", "Catalog to search on. If not provided, all available catalogs are searched.")
53+
fs.StringVar(&i.CatalogName, "catalog", "", "Catalog to search on. If not provided, all available catalogs are searched.")
5054
fs.StringVarP(&i.Selector, "selector", "l", "", "Selector (label query) to filter catalogs on, supports '=', '==', and '!='")
5155
fs.StringVarP(&i.OutputFormat, "output", "o", "", "output format. One of: (yaml|json)")
5256
fs.BoolVar(&i.ListVersions, "list-versions", false, "List all versions available for each package")

internal/cmd/internal/olmv1/printing.go

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import (
1212
"time"
1313

1414
"github.com/blang/semver/v4"
15-
"github.com/operator-framework/operator-registry/alpha/declcfg"
16-
"github.com/operator-framework/operator-registry/alpha/property"
1715
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1816
"k8s.io/apimachinery/pkg/util/duration"
1917
"k8s.io/apimachinery/pkg/util/json"
2018

2119
olmv1 "github.com/operator-framework/operator-controller/api/v1"
20+
"github.com/operator-framework/operator-registry/alpha/declcfg"
21+
"github.com/operator-framework/operator-registry/alpha/property"
2222
)
2323

2424
func printFormattedExtensions(extensions ...olmv1.ClusterExtension) {
@@ -70,12 +70,8 @@ func printFormattedCatalogs(catalogs ...olmv1.ClusterCatalog) {
7070
}
7171

7272
func printFormattedDeclCfg(w io.Writer, catalogDcfg map[string]*declcfg.DeclarativeConfig, listVersions bool) {
73+
var printedHeaders bool
7374
tw := tabwriter.NewWriter(w, 3, 4, 2, ' ', 0)
74-
if listVersions {
75-
_, _ = fmt.Fprint(tw, "PACKAGE\tCATALOG\tPROVIDER\tVERSION\n")
76-
} else {
77-
_, _ = fmt.Fprint(tw, "PACKAGE\tCATALOG\tPROVIDER\tCHANNELS\n")
78-
}
7975
sortedCatalogs := []string{}
8076
for catalogName := range catalogDcfg {
8177
sortedCatalogs = append(sortedCatalogs, catalogName)
@@ -96,37 +92,20 @@ func printFormattedDeclCfg(w io.Writer, catalogDcfg map[string]*declcfg.Declarat
9692
if listVersions {
9793
for _, b := range dcfg.Bundles {
9894
if pkgProviders[b.Package] == nil {
99-
pkgProviders[b.Package] = &dcfgPrintMeta{}
100-
}
101-
if pkgProviders[b.Package].versions == nil {
102-
pkgProviders[b.Package].versions = []semver.Version{}
103-
}
104-
for _, versionProp := range b.Properties {
105-
if versionProp.Type == property.TypePackage {
106-
var pkgProp property.Package
107-
if err := json.Unmarshal(versionProp.Value, &pkgProp); err == nil && len(pkgProp.Version) > 0 {
108-
if parsedVersion, err := semver.Parse(pkgProp.Version); err == nil {
109-
pkgProviders[b.Package].versions = append(pkgProviders[b.Package].versions, parsedVersion)
110-
}
111-
}
112-
continue
113-
}
114-
if versionProp.Type == property.TypeCSVMetadata {
115-
var pkgProp property.CSVMetadata
116-
if err := json.Unmarshal(versionProp.Value, &pkgProp); err == nil && len(pkgProp.Provider.Name) > 0 {
117-
pkgProviders[b.Package].provider = pkgProp.Provider.Name
118-
}
119-
continue
95+
pkgProviders[b.Package] = &dcfgPrintMeta{
96+
versions: []semver.Version{},
97+
provider: getCSVProvider(&b),
12098
}
12199
}
100+
bundleVersion, err := getBundleVersion(&b)
101+
if err == nil {
102+
pkgProviders[b.Package].versions = append(pkgProviders[b.Package].versions, bundleVersion)
103+
}
122104
}
123105
} else {
124106
for _, c := range dcfg.Channels {
125107
if pkgProviders[c.Package] == nil {
126-
pkgProviders[c.Package] = &dcfgPrintMeta{}
127-
}
128-
if pkgProviders[c.Package].channels == nil {
129-
pkgProviders[c.Package].channels = []string{}
108+
pkgProviders[c.Package] = &dcfgPrintMeta{channels: []string{}}
130109
}
131110
pkgProviders[c.Package].channels = append(pkgProviders[c.Package].channels, c.Name)
132111
}
@@ -138,6 +117,10 @@ func printFormattedDeclCfg(w io.Writer, catalogDcfg map[string]*declcfg.Declarat
138117
return pkgProviders[p.Name].versions[i].GT(pkgProviders[p.Name].versions[j])
139118
})
140119
for _, v := range pkgProviders[p.Name].versions {
120+
if !printedHeaders {
121+
_, _ = fmt.Fprint(tw, "PACKAGE\tCATALOG\tPROVIDER\tVERSION\n")
122+
printedHeaders = true
123+
}
141124
_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n",
142125
p.Name,
143126
catalogName,
@@ -146,6 +129,10 @@ func printFormattedDeclCfg(w io.Writer, catalogDcfg map[string]*declcfg.Declarat
146129
}
147130
} else {
148131
sort.Strings(pkgProviders[p.Name].channels)
132+
if !printedHeaders {
133+
_, _ = fmt.Fprint(tw, "PACKAGE\tCATALOG\tPROVIDER\tCHANNELS\n")
134+
printedHeaders = true
135+
}
149136
_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n",
150137
p.Name,
151138
catalogName,
@@ -154,9 +141,40 @@ func printFormattedDeclCfg(w io.Writer, catalogDcfg map[string]*declcfg.Declarat
154141
}
155142
}
156143
}
144+
if !printedHeaders {
145+
_, _ = fmt.Fprint(tw, "No resources found.\n")
146+
}
157147
_ = tw.Flush()
158148
}
159149

150+
func getBundleVersion(bundle *declcfg.Bundle) (semver.Version, error) {
151+
for _, p := range bundle.Properties {
152+
if p.Type == property.TypePackage {
153+
var pkgProp property.Package
154+
if err := json.Unmarshal(p.Value, &pkgProp); err == nil && len(pkgProp.Version) > 0 {
155+
parsedVersion, err := semver.Parse(pkgProp.Version)
156+
if err != nil {
157+
return semver.Version{}, err
158+
}
159+
return parsedVersion, nil
160+
}
161+
}
162+
}
163+
return semver.Version{}, fmt.Errorf("no version property")
164+
}
165+
166+
func getCSVProvider(bundle *declcfg.Bundle) string {
167+
for _, csvProp := range bundle.Properties {
168+
if csvProp.Type == property.TypeCSVMetadata {
169+
var pkgProp property.CSVMetadata
170+
if err := json.Unmarshal(csvProp.Value, &pkgProp); err == nil && len(pkgProp.Provider.Name) > 0 {
171+
return pkgProp.Provider.Name
172+
}
173+
}
174+
}
175+
return ""
176+
}
177+
160178
func printDeclCfgJSON(w io.Writer, catalogDcfg map[string]*declcfg.DeclarativeConfig) {
161179
for _, dcfg := range catalogDcfg {
162180
_ = declcfg.WriteJSON(*dcfg, w)

internal/pkg/v1/action/catalog_installed_get.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package action
22

33
import (
44
"context"
5+
"fmt"
56

7+
"k8s.io/apimachinery/pkg/labels"
68
"k8s.io/apimachinery/pkg/types"
79
"sigs.k8s.io/controller-runtime/pkg/client"
810

@@ -15,6 +17,8 @@ type CatalogInstalledGet struct {
1517
config *action.Configuration
1618
CatalogName string
1719

20+
Selector string
21+
1822
Logf func(string, ...interface{})
1923
}
2024

@@ -41,7 +45,15 @@ func (i *CatalogInstalledGet) Run(ctx context.Context) ([]olmv1.ClusterCatalog,
4145

4246
// list
4347
var result olmv1.ClusterCatalogList
44-
err := i.config.Client.List(ctx, &result, &client.ListOptions{})
48+
listOptions := &client.ListOptions{}
49+
if len(i.Selector) > 0 {
50+
labelSelector, err := labels.Parse(i.Selector)
51+
if err != nil {
52+
return nil, fmt.Errorf("unable to parse selector %s: %v", i.Selector, err)
53+
}
54+
listOptions.LabelSelector = labelSelector
55+
}
56+
err := i.config.Client.List(ctx, &result, listOptions)
4557

4658
return result.Items, err
4759
}

internal/pkg/v1/action/catalog_installed_get_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,23 @@ var _ = Describe("CatalogInstalledGet", func() {
7979
Expect(err).NotTo(BeNil())
8080
Expect(catalogs).To(BeEmpty())
8181
})
82+
83+
It("returns catalogs matching labels when specified", func() {
84+
initCatalogs := []client.Object{
85+
newClusterCatalog("cat-a1"),
86+
newClusterCatalog("cat-a2"),
87+
newClusterCatalog("cat-b1"),
88+
newClusterCatalog("cat-b2"),
89+
}
90+
initCatalogs[0].SetLabels(map[string]string{"foo": "bar"})
91+
initCatalogs[1].SetLabels(map[string]string{"foo": "bar"})
92+
93+
cfg := setupEnv(initCatalogs...)
94+
95+
getter := internalaction.NewCatalogInstalledGet(&cfg)
96+
getter.Selector = "foo=bar"
97+
catalogs, err := getter.Run(context.TODO())
98+
Expect(err).To(BeNil())
99+
Expect(catalogs).To(HaveLen(2))
100+
})
82101
})

internal/pkg/v1/action/catalog_search.go

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,19 @@ import (
55
"fmt"
66
"time"
77

8-
catalogClient "github.com/operator-framework/kubectl-operator/internal/pkg/v1/client"
98
"k8s.io/apimachinery/pkg/api/meta"
109
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11-
"k8s.io/apimachinery/pkg/labels"
12-
"k8s.io/apimachinery/pkg/types"
13-
"sigs.k8s.io/controller-runtime/pkg/client"
1410

15-
"github.com/operator-framework/kubectl-operator/pkg/action"
1611
olmv1 "github.com/operator-framework/operator-controller/api/v1"
1712
"github.com/operator-framework/operator-registry/alpha/declcfg"
13+
14+
catalogClient "github.com/operator-framework/kubectl-operator/internal/pkg/v1/client"
15+
"github.com/operator-framework/kubectl-operator/pkg/action"
1816
)
1917

2018
type CatalogSearch struct {
2119
config *action.Configuration
22-
Catalog string
20+
CatalogName string
2321
OutputFormat string
2422
Selector string
2523
ListVersions bool
@@ -38,51 +36,36 @@ func NewCatalogSearch(cfg *action.Configuration) *CatalogSearch {
3836
}
3937

4038
func (i *CatalogSearch) Run(ctx context.Context) (map[string]*declcfg.DeclarativeConfig, error) {
41-
var catalogList []olmv1.ClusterCatalog
42-
if len(i.Catalog) == 0 {
43-
var result olmv1.ClusterCatalogList
44-
listOptions := &client.ListOptions{}
45-
if len(i.Selector) > 0 {
46-
labelSelector, err := labels.Parse(i.Selector)
47-
if err != nil {
48-
return nil, fmt.Errorf("unable to parse selector %s: %v", i.Selector, err)
49-
}
50-
listOptions.LabelSelector = labelSelector
51-
}
52-
if err := i.config.Client.List(ctx, &result, listOptions); err != nil {
53-
return nil, err
54-
}
55-
if len(result.Items) == 0 {
56-
if len(i.Selector) > 0 {
57-
return nil, fmt.Errorf("no serving catalogs matching label selector %v found", i.Selector)
58-
}
59-
return nil, fmt.Errorf("no serving catalogs found")
60-
}
61-
for _, c := range result.Items {
62-
if isCatalogServing(c) {
63-
catalogList = append(catalogList, c)
64-
}
65-
}
66-
} else {
67-
var c olmv1.ClusterCatalog
68-
if err := i.config.Client.Get(ctx, types.NamespacedName{Name: i.Catalog}, &c, &client.GetOptions{}); err != nil {
69-
return nil, err
39+
if len(i.Timeout) > 0 {
40+
catalogListTimeout, err := time.ParseDuration(i.Timeout)
41+
if err != nil {
42+
return nil, fmt.Errorf("failed to parse timeout %s: %w", i.Timeout, err)
7043
}
44+
i.config.Config.Timeout = catalogListTimeout
45+
}
46+
var catalogList []olmv1.ClusterCatalog
47+
listCmd := CatalogInstalledGet{Selector: i.Selector, CatalogName: i.CatalogName}
48+
result, err := listCmd.Run(ctx)
49+
if err != nil {
50+
return nil, err
51+
}
52+
for _, c := range result {
7153
if isCatalogServing(c) {
72-
catalogList = []olmv1.ClusterCatalog{c}
54+
catalogList = append(catalogList, c)
7355
}
7456
}
7557
if len(catalogList) == 0 {
76-
return nil, fmt.Errorf("failed to query for catalog contents: catalog(s) unhealthy")
77-
}
78-
79-
if len(i.Timeout) > 0 {
80-
if catalogListTimeout, err := time.ParseDuration(i.Timeout); err == nil {
81-
i.config.Config.Timeout = catalogListTimeout
58+
if len(i.CatalogName) != 0 {
59+
return nil, fmt.Errorf("failed to query for catalog contents: catalog(s) unhealthy")
60+
}
61+
if len(i.Selector) > 0 {
62+
return nil, fmt.Errorf("no serving catalogs matching label selector %v found", i.Selector)
8263
}
64+
return nil, fmt.Errorf("no serving catalogs found")
8365
}
8466
searchClientV1 := catalogClient.NewK8sClient(i.config.Config, i.config.Client, i.CatalogdNamespace).V1()
8567
catalogDeclCfg := map[string]*declcfg.DeclarativeConfig{}
68+
foundPackage := len(i.Package) == 0 // whether to check for empty package query
8669
for _, c := range catalogList {
8770
catalogContent, err := searchClientV1.All(ctx, &c)
8871
if err != nil {
@@ -98,7 +81,22 @@ func (i *CatalogSearch) Run(ctx context.Context) (map[string]*declcfg.Declarativ
9881
continue
9982
}
10083

101-
catalogDeclCfg[c.Name] = filterPackage(declConfigContents, i.Package)
84+
filteredContents := filterPackage(declConfigContents, i.Package)
85+
86+
if len(filteredContents.Packages) > 0 {
87+
catalogDeclCfg[c.Name] = filteredContents
88+
foundPackage = true
89+
}
90+
}
91+
if !foundPackage {
92+
// package name was specified and query was empty across all available catalogs.
93+
if len(i.CatalogName) != 0 {
94+
return nil, fmt.Errorf("package %s was not found in ClusterCatalog %s", i.Package, i.CatalogName)
95+
}
96+
if len(i.Selector) > 0 {
97+
return nil, fmt.Errorf("package %s was not found in ClusterCatalogs matching label %s", i.Package, i.Selector)
98+
}
99+
return nil, fmt.Errorf("package %s was not found in any serving ClusterCatalog", i.Package)
102100
}
103101
return catalogDeclCfg, nil
104102
}

0 commit comments

Comments
 (0)