Skip to content

Commit 4780ff4

Browse files
committed
catalog install->add, uninstall->remove; add list-available catalog selector flag
1 parent ab94f15 commit 4780ff4

File tree

8 files changed

+134
-85
lines changed

8 files changed

+134
-85
lines changed

internal/cmd/catalog.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ func newCatalogCmd(cfg *action.Configuration) *cobra.Command {
1212
Short: "Manage operator catalogs",
1313
}
1414
cmd.AddCommand(
15-
newCatalogInstallCmd(cfg),
15+
newCatalogAddCmd(cfg),
1616
newCatalogListCmd(cfg),
17-
newCatalogUninstallCmd(cfg),
17+
newCatalogRemoveCmd(cfg),
1818
)
1919
return cmd
2020
}

internal/cmd/catalog_install.go renamed to internal/cmd/catalog_add.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,34 @@ import (
1212
"github.com/joelanford/kubectl-operator/internal/pkg/log"
1313
)
1414

15-
func newCatalogInstallCmd(cfg *action.Configuration) *cobra.Command {
16-
i := action.NewInstallCatalog(cfg)
15+
func newCatalogAddCmd(cfg *action.Configuration) *cobra.Command {
16+
a := action.NewAddCatalog(cfg)
1717

1818
cmd := &cobra.Command{
19-
Use: "install <index_image>",
20-
Short: "Install an operator catalog",
19+
Use: "add <index_image>",
20+
Short: "Add an operator catalog",
2121
Args: cobra.ExactArgs(1),
2222
PreRun: func(cmd *cobra.Command, args []string) {
2323
regLogger := logrus.New()
2424
regLogger.SetOutput(ioutil.Discard)
25-
i.RegistryOptions = []containerdregistry.RegistryOption{
25+
a.RegistryOptions = []containerdregistry.RegistryOption{
2626
containerdregistry.WithLog(logrus.NewEntry(regLogger)),
2727
}
2828
},
2929
Run: func(cmd *cobra.Command, args []string) {
30-
ctx, cancel := context.WithTimeout(cmd.Context(), i.InstallTimeout)
30+
ctx, cancel := context.WithTimeout(cmd.Context(), a.AddTimeout)
3131
defer cancel()
3232

33-
i.IndexImage = args[0]
33+
a.IndexImage = args[0]
3434

35-
cs, err := i.Run(ctx)
35+
cs, err := a.Run(ctx)
3636
if err != nil {
37-
log.Fatalf("failed to install catalog: %v", err)
37+
log.Fatalf("failed to add catalog: %v", err)
3838
}
3939
log.Printf("created catalogsource %q\n", cs.Name)
4040
},
4141
}
42-
i.BindFlags(cmd.Flags())
42+
a.BindFlags(cmd.Flags())
4343

4444
return cmd
4545
}

internal/cmd/catalog_uninstall.go renamed to internal/cmd/catalog_remove.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ import (
77
"github.com/joelanford/kubectl-operator/internal/pkg/log"
88
)
99

10-
func newCatalogUninstallCmd(cfg *action.Configuration) *cobra.Command {
11-
u := action.NewUninstallCatalog(cfg)
10+
func newCatalogRemoveCmd(cfg *action.Configuration) *cobra.Command {
11+
u := action.NewRemoveCatalog(cfg)
1212
cmd := &cobra.Command{
13-
Use: "uninstall <catalog_name>",
14-
Short: "Uninstall an operator catalog",
13+
Use: "remove <catalog_name>",
14+
Short: "Remove a operator catalog",
1515
Args: cobra.ExactArgs(1),
1616
Run: func(cmd *cobra.Command, args []string) {
1717
u.CatalogName = args[0]
1818

1919
if err := u.Run(cmd.Context()); err != nil {
20-
log.Fatalf("failed to uninstall catalog %q: %v", u.CatalogName, err)
20+
log.Fatalf("failed to remove catalog %q: %v", u.CatalogName, err)
2121
}
22-
log.Printf("catalogsource %q uninstalled", u.CatalogName)
22+
log.Printf("catalogsource %q removed", u.CatalogName)
2323
},
2424
}
2525

internal/cmd/operator_list_available.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,6 @@ func newListAvailableCmd(cfg *action.Configuration) *cobra.Command {
5050
_ = tw.Flush()
5151
},
5252
}
53+
l.BindFlags(cmd.Flags())
5354
return cmd
5455
}

internal/pkg/action/catalog_install.go renamed to internal/pkg/action/catalog_add.go

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,102 +18,102 @@ import (
1818
"github.com/joelanford/kubectl-operator/internal/pkg/log"
1919
)
2020

21-
type InstallCatalog struct {
21+
type AddCatalog struct {
2222
config *Configuration
2323

2424
IndexImage string
2525
DisplayName string
2626
Publisher string
27-
InstallTimeout time.Duration
27+
AddTimeout time.Duration
2828
CleanupTimeout time.Duration
2929

3030
RegistryOptions []containerdregistry.RegistryOption
3131

3232
registry *containerdregistry.Registry
3333
}
3434

35-
func NewInstallCatalog(cfg *Configuration) *InstallCatalog {
36-
return &InstallCatalog{
35+
func NewAddCatalog(cfg *Configuration) *AddCatalog {
36+
return &AddCatalog{
3737
config: cfg,
3838
}
3939
}
4040

41-
func (i *InstallCatalog) BindFlags(fs *pflag.FlagSet) {
42-
fs.StringVarP(&i.DisplayName, "display-name", "d", "", "display name of the index")
43-
fs.StringVarP(&i.Publisher, "publisher", "p", "", "publisher of the index")
44-
fs.DurationVarP(&i.InstallTimeout, "timeout", "t", time.Minute, "the amount of time to wait before cancelling the install")
45-
fs.DurationVar(&i.CleanupTimeout, "cleanup-timeout", time.Minute, "the amount to time to wait before cancelling cleanup")
41+
func (a *AddCatalog) BindFlags(fs *pflag.FlagSet) {
42+
fs.StringVarP(&a.DisplayName, "display-name", "d", "", "display name of the index")
43+
fs.StringVarP(&a.Publisher, "publisher", "p", "", "publisher of the index")
44+
fs.DurationVarP(&a.AddTimeout, "timeout", "t", time.Minute, "the amount of time to wait before cancelling the catalog addition")
45+
fs.DurationVar(&a.CleanupTimeout, "cleanup-timeout", time.Minute, "the amount to time to wait before cancelling cleanup")
4646
}
4747

48-
func (i *InstallCatalog) Run(ctx context.Context) (*v1alpha1.CatalogSource, error) {
48+
func (a *AddCatalog) Run(ctx context.Context) (*v1alpha1.CatalogSource, error) {
4949
var err error
50-
i.registry, err = containerdregistry.NewRegistry(i.RegistryOptions...)
50+
a.registry, err = containerdregistry.NewRegistry(a.RegistryOptions...)
5151
if err != nil {
5252
return nil, err
5353
}
5454

5555
defer func() {
56-
if err := i.registry.Destroy(); err != nil {
56+
if err := a.registry.Destroy(); err != nil {
5757
log.Printf("registry cleanup: %v", err)
5858
}
5959
}()
6060

61-
imageRef, err := container.ImageFromString(i.IndexImage)
61+
imageRef, err := container.ImageFromString(a.IndexImage)
6262
if err != nil {
6363
return nil, err
6464
}
6565
csKey := types.NamespacedName{
66-
Namespace: i.config.Namespace,
66+
Namespace: a.config.Namespace,
6767
Name: imageRef.Name,
6868
}
6969

70-
labels, err := i.labelsFor(ctx, i.IndexImage)
70+
labels, err := a.labelsFor(ctx, a.IndexImage)
7171
if err != nil {
7272
return nil, err
7373
}
7474

75-
i.setDefaults(labels)
75+
a.setDefaults(labels)
7676

7777
opts := []catalog.Option{
78-
catalog.Image(i.IndexImage),
79-
catalog.DisplayName(i.DisplayName),
80-
catalog.Publisher(i.Publisher),
78+
catalog.Image(a.IndexImage),
79+
catalog.DisplayName(a.DisplayName),
80+
catalog.Publisher(a.Publisher),
8181
}
8282
cs := catalog.Build(csKey, opts...)
83-
if err := i.install(ctx, cs); err != nil {
84-
defer i.cleanup(cs)
83+
if err := a.add(ctx, cs); err != nil {
84+
defer a.cleanup(cs)
8585
return nil, err
8686
}
8787
return cs, nil
8888
}
8989

90-
func (i *InstallCatalog) labelsFor(ctx context.Context, indexImage string) (map[string]string, error) {
90+
func (a *AddCatalog) labelsFor(ctx context.Context, indexImage string) (map[string]string, error) {
9191
simpleRef := image.SimpleReference(indexImage)
92-
if err := i.registry.Pull(ctx, simpleRef); err != nil {
92+
if err := a.registry.Pull(ctx, simpleRef); err != nil {
9393
return nil, fmt.Errorf("pull image: %v", err)
9494
}
95-
labels, err := i.registry.Labels(ctx, simpleRef)
95+
labels, err := a.registry.Labels(ctx, simpleRef)
9696
if err != nil {
9797
return nil, fmt.Errorf("get image labels: %v", err)
9898
}
9999
return labels, nil
100100
}
101101

102-
func (i *InstallCatalog) setDefaults(labels map[string]string) {
103-
if i.DisplayName == "" {
102+
func (a *AddCatalog) setDefaults(labels map[string]string) {
103+
if a.DisplayName == "" {
104104
if v, ok := labels["operators.operatorframework.io.index.display-name"]; ok {
105-
i.DisplayName = v
105+
a.DisplayName = v
106106
}
107107
}
108-
if i.Publisher == "" {
108+
if a.Publisher == "" {
109109
if v, ok := labels["operators.operatorframework.io.index.publisher"]; ok {
110-
i.Publisher = v
110+
a.Publisher = v
111111
}
112112
}
113113
}
114114

115-
func (i *InstallCatalog) install(ctx context.Context, cs *v1alpha1.CatalogSource) error {
116-
if err := i.config.Client.Create(ctx, cs); err != nil {
115+
func (a *AddCatalog) add(ctx context.Context, cs *v1alpha1.CatalogSource) error {
116+
if err := a.config.Client.Create(ctx, cs); err != nil {
117117
return fmt.Errorf("create catalogsource: %v", err)
118118
}
119119

@@ -122,7 +122,7 @@ func (i *InstallCatalog) install(ctx context.Context, cs *v1alpha1.CatalogSource
122122
return fmt.Errorf("get catalogsource key: %v", err)
123123
}
124124
if err := wait.PollImmediateUntil(time.Millisecond*250, func() (bool, error) {
125-
if err := i.config.Client.Get(ctx, csKey, cs); err != nil {
125+
if err := a.config.Client.Get(ctx, csKey, cs); err != nil {
126126
return false, err
127127
}
128128
if cs.Status.GRPCConnectionState != nil {
@@ -137,10 +137,10 @@ func (i *InstallCatalog) install(ctx context.Context, cs *v1alpha1.CatalogSource
137137
return nil
138138
}
139139

140-
func (i *InstallCatalog) cleanup(cs *v1alpha1.CatalogSource) {
141-
ctx, cancel := context.WithTimeout(context.Background(), i.CleanupTimeout)
140+
func (a *AddCatalog) cleanup(cs *v1alpha1.CatalogSource) {
141+
ctx, cancel := context.WithTimeout(context.Background(), a.CleanupTimeout)
142142
defer cancel()
143-
if err := i.config.Client.Delete(ctx, cs); err != nil {
143+
if err := a.config.Client.Delete(ctx, cs); err != nil {
144144
log.Printf("delete catalogsource %q: %v", cs.Name, err)
145145
}
146146
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package action
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
8+
)
9+
10+
type RemoveCatalog struct {
11+
config *Configuration
12+
13+
CatalogName string
14+
}
15+
16+
func NewRemoveCatalog(cfg *Configuration) *RemoveCatalog {
17+
return &RemoveCatalog{
18+
config: cfg,
19+
}
20+
}
21+
22+
func (r *RemoveCatalog) Run(ctx context.Context) error {
23+
cs := v1alpha1.CatalogSource{}
24+
cs.SetNamespace(r.config.Namespace)
25+
cs.SetName(r.CatalogName)
26+
if err := r.config.Client.Delete(ctx, &cs); err != nil {
27+
return fmt.Errorf("delete catalogsource %q: %v", cs.Name, err)
28+
}
29+
return nil
30+
}

internal/pkg/action/catalog_uninstall.go

Lines changed: 0 additions & 30 deletions
This file was deleted.

internal/pkg/action/operator_list_available.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,70 @@ package action
22

33
import (
44
"context"
5+
"fmt"
6+
"strings"
57

68
v1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1"
9+
"github.com/spf13/pflag"
10+
"k8s.io/apimachinery/pkg/types"
11+
"sigs.k8s.io/controller-runtime/pkg/client"
712
)
813

914
type ListAvailableOperators struct {
1015
config *Configuration
16+
17+
Catalog NamespacedName
1118
}
1219

1320
func NewListAvailableOperators(cfg *Configuration) *ListAvailableOperators {
14-
return &ListAvailableOperators{cfg}
21+
return &ListAvailableOperators{
22+
config: cfg,
23+
}
1524
}
1625

1726
func (l *ListAvailableOperators) Run(ctx context.Context) ([]v1.PackageManifest, error) {
1827
pms := v1.PackageManifestList{}
19-
if err := l.config.Client.List(ctx, &pms); err != nil {
28+
29+
labelSelector := client.MatchingLabels{}
30+
if l.Catalog.Name != "" {
31+
labelSelector["catalog"] = l.Catalog.Name
32+
}
33+
if l.Catalog.Namespace != "" {
34+
labelSelector["catalog-namespace"] = l.Catalog.Namespace
35+
}
36+
if err := l.config.Client.List(ctx, &pms, labelSelector); err != nil {
2037
return nil, err
2138
}
2239
return pms.Items, nil
2340
}
41+
42+
func (l *ListAvailableOperators) BindFlags(fs *pflag.FlagSet) {
43+
fs.VarP(&l.Catalog, "catalog", "c", "catalog to query (default: search all cluster catalogs)")
44+
}
45+
46+
type NamespacedName struct {
47+
types.NamespacedName
48+
}
49+
50+
func (f *NamespacedName) Set(str string) error {
51+
split := strings.Split(str, "/")
52+
switch len(split) {
53+
case 0:
54+
case 1:
55+
f.Name = split[0]
56+
case 2:
57+
f.Namespace = split[0]
58+
f.Name = split[1]
59+
default:
60+
return fmt.Errorf("invalid namespaced name value %q", str)
61+
}
62+
return nil
63+
}
64+
65+
func (f NamespacedName) String() string {
66+
return f.NamespacedName.String()
67+
}
68+
69+
func (f NamespacedName) Type() string {
70+
return "NamespacedNameValue"
71+
}

0 commit comments

Comments
 (0)