Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ require (
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.1 // indirect
github.com/go-git/go-git/v5 v5.13.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
Expand All @@ -71,14 +74,18 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/h2non/filetype v1.1.3 // indirect
github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/joelanford/ignore v0.1.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/moby/sys/capability v0.3.0 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
Expand All @@ -87,6 +94,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
Expand Down Expand Up @@ -116,6 +124,7 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
Expand Down
20 changes: 20 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -103,6 +105,12 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA=
github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE=
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
Expand Down Expand Up @@ -166,6 +174,8 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
Expand All @@ -184,6 +194,10 @@ github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/joelanford/ignore v0.1.1 h1:vKky5RDoPT+WbONrbQBgOn95VV/UPh4ejlyAbbzgnQk=
github.com/joelanford/ignore v0.1.1/go.mod h1:8eho/D8fwQ3rIXrLwE23AaeaGDNXqLE9QJ3zJ4LIPCw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
Expand All @@ -204,6 +218,8 @@ github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBW
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
Expand All @@ -221,6 +237,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
Expand Down Expand Up @@ -471,6 +489,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
58 changes: 58 additions & 0 deletions internal/cmd/internal/olmv1/catalog_search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package olmv1

import (
"os"

"github.com/operator-framework/kubectl-operator/internal/cmd/internal/log"
v1action "github.com/operator-framework/kubectl-operator/internal/pkg/v1/action"
"github.com/operator-framework/kubectl-operator/pkg/action"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

// NewCatalogInstalledGetCmd handles get commands in the form of:
// catalog(s) [catalog_name] - this will either list all the installed operators
// if no catalog_name has been provided or display the details of the specific
// one otherwise
func NewCatalogSearchCmd(cfg *action.Configuration) *cobra.Command {
i := v1action.NewCatalogSearch(cfg)
i.Logf = log.Printf

cmd := &cobra.Command{
Use: "catalog",
Aliases: []string{"catalogs"},
Args: cobra.RangeArgs(0, 1),
Short: "Search catalogs for installable operators matching parameters",
Run: func(cmd *cobra.Command, args []string) {
catalogContents, err := i.Run(cmd.Context())
if err != nil {
log.Fatalf("failed querying catalog(s): %v", err)
}
switch i.OutputFormat {
case "", "table":
printFormattedDeclCfg(os.Stdout, catalogContents, i.ListVersions)
case "json":
printDeclCfgJSON(os.Stdout, catalogContents)
case "yaml":
printDeclCfgYAML(os.Stdout, catalogContents)
default:
log.Fatalf("unsupported output format %s: allwed formats are (json|yaml|table)", i.OutputFormat)
}
},
}
bindCatalogSearchFlags(cmd.Flags(), i)

return cmd
}

func bindCatalogSearchFlags(fs *pflag.FlagSet, i *v1action.CatalogSearch) {
fs.StringVar(&i.Catalog, "catalog", "", "Catalog to search on. If not provided, all available catalogs are searched.")
fs.StringVarP(&i.Selector, "selector", "l", "", "Selector (label query) to filter catalogs on, supports '=', '==', and '!='")
fs.StringVarP(&i.OutputFormat, "output", "o", "", "output format. One of: (yaml|json)")
fs.BoolVar(&i.ListVersions, "list-versions", false, "List all versions available for each package")
fs.StringVar(&i.Package, "package", "", "Search for package by name. If empty, all available packages will be listed")
fs.StringVar(&i.CatalogdNamespace, "catalogd-namespace", "olmv1-system", "Namespace for the catalogd controller")
fs.StringVar(&i.Timeout, "timeout", "5m", "Timeout for fetching catalog contents")
// installable vs uninstallable, all versions, channels
// fs.StringVar(&i.showAll, "image", "", "Image reference for the catalog source. Leave unset to retain the current image.")
}
107 changes: 107 additions & 0 deletions internal/cmd/internal/olmv1/printing.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package olmv1
import (
"cmp"
"fmt"
"io"
"os"
"slices"
"sort"
"strings"
"text/tabwriter"
"time"

"github.com/blang/semver/v4"
"github.com/operator-framework/operator-registry/alpha/declcfg"
"github.com/operator-framework/operator-registry/alpha/property"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/duration"
"k8s.io/apimachinery/pkg/util/json"

olmv1 "github.com/operator-framework/operator-controller/api/v1"
)
Expand Down Expand Up @@ -63,6 +69,107 @@ func printFormattedCatalogs(catalogs ...olmv1.ClusterCatalog) {
_ = tw.Flush()
}

func printFormattedDeclCfg(w io.Writer, catalogDcfg map[string]*declcfg.DeclarativeConfig, listVersions bool) {
tw := tabwriter.NewWriter(w, 3, 4, 2, ' ', 0)
if listVersions {
_, _ = fmt.Fprint(tw, "PACKAGE\tCATALOG\tPROVIDER\tVERSION\n")
} else {
_, _ = fmt.Fprint(tw, "PACKAGE\tCATALOG\tPROVIDER\tCHANNELS\n")
}
sortedCatalogs := []string{}
for catalogName := range catalogDcfg {
sortedCatalogs = append(sortedCatalogs, catalogName)
}
sort.Strings(sortedCatalogs)
for _, catalogName := range sortedCatalogs {
dcfg := catalogDcfg[catalogName]
type dcfgPrintMeta struct {
provider string
channels []string
versions []semver.Version
}
pkgProviders := map[string]*dcfgPrintMeta{}
sort.SliceStable(dcfg.Packages, func(i, j int) bool {
return dcfg.Packages[i].Name < dcfg.Packages[j].Name
})

if listVersions {
for _, b := range dcfg.Bundles {
if pkgProviders[b.Package] == nil {
pkgProviders[b.Package] = &dcfgPrintMeta{}
}
if pkgProviders[b.Package].versions == nil {
pkgProviders[b.Package].versions = []semver.Version{}
}
for _, versionProp := range b.Properties {
if versionProp.Type == property.TypePackage {
var pkgProp property.Package
if err := json.Unmarshal(versionProp.Value, &pkgProp); err == nil && len(pkgProp.Version) > 0 {
if parsedVersion, err := semver.Parse(pkgProp.Version); err == nil {
pkgProviders[b.Package].versions = append(pkgProviders[b.Package].versions, parsedVersion)
}
}
continue
}
if versionProp.Type == property.TypeCSVMetadata {
var pkgProp property.CSVMetadata
if err := json.Unmarshal(versionProp.Value, &pkgProp); err == nil && len(pkgProp.Provider.Name) > 0 {
pkgProviders[b.Package].provider = pkgProp.Provider.Name
}
continue
}
}
}
} else {
for _, c := range dcfg.Channels {
if pkgProviders[c.Package] == nil {
pkgProviders[c.Package] = &dcfgPrintMeta{}
}
if pkgProviders[c.Package].channels == nil {
pkgProviders[c.Package].channels = []string{}
}
pkgProviders[c.Package].channels = append(pkgProviders[c.Package].channels, c.Name)
}
}

for _, p := range dcfg.Packages {
if listVersions {
sort.SliceStable(pkgProviders[p.Name].versions, func(i, j int) bool {
return pkgProviders[p.Name].versions[i].GT(pkgProviders[p.Name].versions[j])
})
for _, v := range pkgProviders[p.Name].versions {
_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n",
p.Name,
catalogName,
pkgProviders[p.Name].provider,
v)
}
} else {
sort.Strings(pkgProviders[p.Name].channels)
_, _ = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n",
p.Name,
catalogName,
pkgProviders[p.Name].provider,
strings.Join(pkgProviders[p.Name].channels, ","))
}
}
}
_ = tw.Flush()
}

func printDeclCfgJSON(w io.Writer, catalogDcfg map[string]*declcfg.DeclarativeConfig) {
for _, dcfg := range catalogDcfg {
_ = declcfg.WriteJSON(*dcfg, w)
}
}

func printDeclCfgYAML(w io.Writer, catalogDcfg map[string]*declcfg.DeclarativeConfig) {
for _, dcfg := range catalogDcfg {
_ = declcfg.WriteYAML(*dcfg, w)
_, _ = w.Write([]byte("---\n"))
}
}

// sortExtensions sorts extensions in place and uses the following sorting order:
// name (asc), version (desc)
func sortExtensions(extensions []olmv1.ClusterExtension) {
Expand Down
8 changes: 8 additions & 0 deletions internal/cmd/olmv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,20 @@ func newOlmV1Cmd(cfg *action.Configuration) *cobra.Command {
}
installCmd.AddCommand(olmv1.NewExtensionInstallCmd(cfg))

searchCmd := &cobra.Command{
Use: "search",
Short: "Search for packages",
Long: "Search one or all available catalogs for packages or versions",
}
searchCmd.AddCommand(olmv1.NewCatalogSearchCmd(cfg))

cmd.AddCommand(
installCmd,
getCmd,
createCmd,
deleteCmd,
updateCmd,
searchCmd,
)

return cmd
Expand Down
Loading
Loading