Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ import (
"github.com/operator-framework/kubectl-operator/pkg/action"
)

func NewOperatorInstallCmd(cfg *action.Configuration) *cobra.Command {
i := v1action.NewOperatorInstall(cfg)
func NewExtensionInstallCmd(cfg *action.Configuration) *cobra.Command {
i := v1action.NewExtensionInstall(cfg)
i.Logf = log.Printf

cmd := &cobra.Command{
Use: "install <operator>",
Short: "Install an operator",
Use: "install <extension>",
Short: "Install an extension",
Comment on lines +16 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Use: "install <extension>",
Short: "Install an extension",
Use: "install <package name>",
Short: "Install a cluster extension for a package",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about replacing extension with package name here. I think commonly and for user-facing purposes you'd say you want to install an (cluster)extension?
Package name seems like an implementation detail at this point and at least to me it could confuse people because we'd have crud operations mentioning (cluster)extension and then a package terminology at the root level.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Ankita. Here is my suggestion

Use:   "install <cluster extension name>",
		Short: "Install a cluster extension",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a simple rename PR and @LalatenduMohanty is working on install/uninstall commands that this comment touches. How about we have those discussions on that incoming PR where they belong?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with redoing the install help text in the v1 install/uninstall commands PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats fine. I will fix it in my PR.

Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
i.Package = args[0]
_, err := i.Run(cmd.Context())
if err != nil {
log.Fatalf("failed to install operator: %v", err)
log.Fatalf("failed to install extension: %v", err)
}
log.Printf("operator %q created", i.Package)
log.Printf("extension %q created", i.Package)
},
}

Expand Down
38 changes: 38 additions & 0 deletions internal/cmd/internal/olmv1/extension_installed_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package olmv1

import (
"github.com/spf13/cobra"

"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"
)

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

cmd := &cobra.Command{
Use: "extension [extension_name]",
Aliases: []string{"extensions [extension_name]"},
Args: cobra.RangeArgs(0, 1),
Short: "Display one or many installed extensions",
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 1 {
i.ExtensionName = args[0]
}
installedExtensions, err := i.Run(cmd.Context())
if err != nil {
log.Fatalf("failed getting installed extension(s): %v", err)
}

printFormattedExtensions(installedExtensions...)
},
}

return cmd
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ import (
"github.com/operator-framework/kubectl-operator/pkg/action"
)

func NewOperatorUninstallCmd(cfg *action.Configuration) *cobra.Command {
u := v1action.NewOperatorUninstall(cfg)
func NewExtensionUninstallCmd(cfg *action.Configuration) *cobra.Command {
u := v1action.NewExtensionUninstall(cfg)
u.Logf = log.Printf

cmd := &cobra.Command{
Use: "uninstall <operator>",
Short: "Uninstall an operator",
Long: `Uninstall deletes the named Operator object.
Use: "uninstall <extension>",
Short: "Uninstall an extension",
Long: `Uninstall deletes the named extension object.
Warning: this command permanently deletes objects from the cluster. If the
uninstalled Operator bundle contains CRDs, the CRDs will be deleted, which
uninstalled extension bundle contains CRDs, the CRDs will be deleted, which
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not use extension and bundle at the same time. Use of bundle is associated with registry v1 content but not much with cluster extension.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no functional change, it's just one-word rename, so I think bundle(s) are still being used to install operators/extensions.

That said, this is a simple rename PR and @LalatenduMohanty is working on install/uninstall commands that this comment touches. How about we have those discussions on that incoming PR where they belong?

cascades to the deletion of all operands.
`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
u.Package = args[0]
if err := u.Run(cmd.Context()); err != nil {
log.Fatalf("uninstall operator: %v", err)
log.Fatalf("uninstall extension: %v", err)
}
log.Printf("deleted operator %q", u.Package)
log.Printf("deleted extension %q", u.Package)
},
}
return cmd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,34 @@ import (
"github.com/operator-framework/kubectl-operator/pkg/action"
)

// NewOperatorUpdateCmd allows updating a selected operator
func NewOperatorUpdateCmd(cfg *action.Configuration) *cobra.Command {
i := v1action.NewOperatorUpdate(cfg)
// NewExtensionUpdateCmd allows updating a selected operator
func NewExtensionUpdateCmd(cfg *action.Configuration) *cobra.Command {
i := v1action.NewExtensionUpdate(cfg)
i.Logf = log.Printf

cmd := &cobra.Command{
Use: "operator <operator>",
Short: "Update an operator",
Use: "extension <extension>",
Short: "Update an extension",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
i.Package = args[0]
_, err := i.Run(cmd.Context())
if err != nil {
log.Fatalf("failed to update operator: %v", err)
log.Fatalf("failed to update extension: %v", err)
}
log.Printf("operator %q updated", i.Package)
log.Printf("extension %q updated", i.Package)
},
}
bindOperatorUpdateFlags(cmd.Flags(), i)
bindExtensionUpdateFlags(cmd.Flags(), i)

return cmd
}

func bindOperatorUpdateFlags(fs *pflag.FlagSet, i *v1action.OperatorUpdate) {
fs.StringVar(&i.Version, "version", "", "desired operator version (single or range) in semVer format. AND operation with channels")
func bindExtensionUpdateFlags(fs *pflag.FlagSet, i *v1action.ExtensionUpdate) {
fs.StringVar(&i.Version, "version", "", "desired extension version (single or range) in semVer format. AND operation with channels")
fs.StringVar(&i.Selector, "selector", "", "filters the set of catalogs used in the bundle selection process. Empty means that all catalogs will be used in the bundle selection process")
fs.StringArrayVar(&i.Channels, "channels", []string{}, "desired channels for operator versions. AND operation with version. Empty list means all available channels will be taken into consideration")
fs.StringArrayVar(&i.Channels, "channels", []string{}, "desired channels for extension versions. AND operation with version. Empty list means all available channels will be taken into consideration")
fs.StringVar(&i.UpgradeConstraintPolicy, "upgrade-constraint-policy", "", "controls whether the upgrade path(s) defined in the catalog are enforced. One of CatalogProvided|SelfCertified), Default: CatalogProvided")
fs.StringToStringVar(&i.Labels, "labels", map[string]string{}, "labels that will be set on the operator")
fs.StringToStringVar(&i.Labels, "labels", map[string]string{}, "labels that will be set on the extension")
fs.BoolVar(&i.IgnoreUnset, "ignore-unset", true, "when enabled, any unset flag value will not be changed. Disabling means that for each unset value a default will be used instead")
}
38 changes: 0 additions & 38 deletions internal/cmd/internal/olmv1/operator_installed_get.go

This file was deleted.

8 changes: 4 additions & 4 deletions internal/cmd/internal/olmv1/printing.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import (
olmv1 "github.com/operator-framework/operator-controller/api/v1"
)

func printFormattedOperators(extensions ...olmv1.ClusterExtension) {
func printFormattedExtensions(extensions ...olmv1.ClusterExtension) {
tw := tabwriter.NewWriter(os.Stdout, 3, 4, 2, ' ', 0)
_, _ = fmt.Fprint(tw, "NAME\tINSTALLED BUNDLE\tVERSION\tSOURCE TYPE\tINSTALLED\tPROGRESSING\tAGE\n")

sortOperators(extensions)
sortExtensions(extensions)
for _, ext := range extensions {
var bundleName, bundleVersion string
if ext.Status.Install != nil {
Expand Down Expand Up @@ -63,9 +63,9 @@ func printFormattedCatalogs(catalogs ...olmv1.ClusterCatalog) {
_ = tw.Flush()
}

// sortOperators sorts operators in place and uses the following sorting order:
// sortExtensions sorts extensions in place and uses the following sorting order:
// name (asc), version (desc)
func sortOperators(extensions []olmv1.ClusterExtension) {
func sortExtensions(extensions []olmv1.ClusterExtension) {
slices.SortFunc(extensions, func(a, b olmv1.ClusterExtension) int {
if a.Status.Install == nil || b.Status.Install == nil {
return cmp.Compare(a.Name, b.Name)
Expand Down
18 changes: 9 additions & 9 deletions internal/cmd/internal/olmv1/printing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ var _ = Describe("SortCatalogs", func() {
})
})

var _ = Describe("SortOperators", func() {
It("sorts operators in correct order", func() {
operators := []olmv1.ClusterExtension{
var _ = Describe("SortExtensions", func() {
It("sorts extensions in correct order", func() {
extensions := []olmv1.ClusterExtension{
newClusterExtension("op-1", "1.0.0"),
newClusterExtension("op-1", "1.0.1"),
newClusterExtension("op-1", "1.0.1-rc4"),
newClusterExtension("op-1", "1.0.1-rc2"),
newClusterExtension("op-2", "2.0.0"),
}
sortOperators(operators)
sortExtensions(extensions)

Expect(operators[0].Status.Install.Bundle.Version).To(Equal("1.0.1"))
Expect(operators[1].Status.Install.Bundle.Version).To(Equal("1.0.1-rc4"))
Expect(operators[2].Status.Install.Bundle.Version).To(Equal("1.0.1-rc2"))
Expect(operators[3].Status.Install.Bundle.Version).To(Equal("1.0.0"))
Expect(operators[4].Status.Install.Bundle.Version).To(Equal("2.0.0"))
Expect(extensions[0].Status.Install.Bundle.Version).To(Equal("1.0.1"))
Expect(extensions[1].Status.Install.Bundle.Version).To(Equal("1.0.1-rc4"))
Expect(extensions[2].Status.Install.Bundle.Version).To(Equal("1.0.1-rc2"))
Expect(extensions[3].Status.Install.Bundle.Version).To(Equal("1.0.0"))
Expect(extensions[4].Status.Install.Bundle.Version).To(Equal("2.0.0"))
})
})

Expand Down
12 changes: 6 additions & 6 deletions internal/cmd/olmv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
func newOlmV1Cmd(cfg *action.Configuration) *cobra.Command {
cmd := &cobra.Command{
Use: "olmv1",
Short: "Manage operators via OLMv1 in a cluster from the command line",
Long: "Manage operators via OLMv1 in a cluster from the command line.",
Short: "Manage extensions via OLMv1 in a cluster from the command line",
Long: "Manage extensions via OLMv1 in a cluster from the command line.",
}

getCmd := &cobra.Command{
Expand All @@ -20,7 +20,7 @@ func newOlmV1Cmd(cfg *action.Configuration) *cobra.Command {
Long: "Display one or many resource(s)",
}
getCmd.AddCommand(
olmv1.NewOperatorInstalledGetCmd(cfg),
olmv1.NewExtensionInstalledGetCmd(cfg),
olmv1.NewCatalogInstalledGetCmd(cfg),
)

Expand All @@ -44,12 +44,12 @@ func newOlmV1Cmd(cfg *action.Configuration) *cobra.Command {
Long: "Update a resource",
}
updateCmd.AddCommand(
olmv1.NewOperatorUpdateCmd(cfg),
olmv1.NewExtensionUpdateCmd(cfg),
)

cmd.AddCommand(
olmv1.NewOperatorInstallCmd(cfg),
olmv1.NewOperatorUninstallCmd(cfg),
olmv1.NewExtensionInstallCmd(cfg),
olmv1.NewExtensionUninstallCmd(cfg),
getCmd,
createCmd,
deleteCmd,
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/v1/action/action_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func buildExtension(packageName string, opts ...extensionOpt) *olmv1.ClusterExte
return ext
}

func updateOperatorConditionStatus(name string, cl client.Client, typ string, status metav1.ConditionStatus) error {
func updateExtensionConditionStatus(name string, cl client.Client, typ string, status metav1.ConditionStatus) error {
var ext olmv1.ClusterExtension
key := types.NamespacedName{Name: name}

Expand Down
22 changes: 11 additions & 11 deletions internal/pkg/v1/action/catalog_installed_get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,31 @@ var _ = Describe("CatalogInstalledGet", func() {
It("returns empty list in case no catalogs were found", func() {
cfg := setupEnv()

getter := internalaction.NewOperatorInstalledGet(&cfg)
operators, err := getter.Run(context.TODO())
getter := internalaction.NewCatalogInstalledGet(&cfg)
catalogs, err := getter.Run(context.TODO())
Expect(err).To(BeNil())
Expect(operators).To(BeEmpty())
Expect(catalogs).To(BeEmpty())
})

It("gets an installed catalog", func() {
cfg := setupEnv(setupTestCatalogs(3)...)

getter := internalaction.NewCatalogInstalledGet(&cfg)
getter.CatalogName = "cat2"
operators, err := getter.Run(context.TODO())
catalogs, err := getter.Run(context.TODO())
Expect(err).To(BeNil())
Expect(operators).NotTo(BeEmpty())
Expect(operators).To(HaveLen(1))
Expect(operators[0].Name).To(Equal("cat2"))
Expect(catalogs).NotTo(BeEmpty())
Expect(catalogs).To(HaveLen(1))
Expect(catalogs[0].Name).To(Equal("cat2"))
})

It("returns an empty list when an installed catalog was not found", func() {
cfg := setupEnv()

getter := internalaction.NewOperatorInstalledGet(&cfg)
getter.OperatorName = "cat2"
operators, err := getter.Run(context.TODO())
getter := internalaction.NewCatalogInstalledGet(&cfg)
getter.CatalogName = "cat2"
catalogs, err := getter.Run(context.TODO())
Expect(err).NotTo(BeNil())
Expect(operators).To(BeEmpty())
Expect(catalogs).To(BeEmpty())
})
})
2 changes: 1 addition & 1 deletion internal/pkg/v1/action/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import "errors"
var (
ErrNoResourcesFound = errors.New("no resources found")
ErrNameAndSelector = errors.New("name cannot be provided when a selector is specified")
ErrNoChange = errors.New("no changes detected - operator already in desired state")
ErrNoChange = errors.New("no changes detected - extension already in desired state")
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@ import (
"github.com/operator-framework/kubectl-operator/pkg/action"
)

type OperatorInstall struct {
type ExtensionInstall struct {
config *action.Configuration

Package string

Logf func(string, ...interface{})
}

func NewOperatorInstall(cfg *action.Configuration) *OperatorInstall {
return &OperatorInstall{
func NewExtensionInstall(cfg *action.Configuration) *ExtensionInstall {
return &ExtensionInstall{
config: cfg,
Logf: func(string, ...interface{}) {},
}
}

func (i *OperatorInstall) Run(ctx context.Context) (*olmv1.ClusterExtension, error) {
func (i *ExtensionInstall) Run(ctx context.Context) (*olmv1.ClusterExtension, error) {
// TODO(developer): Lookup package information when the OLMv1 equivalent of the
// packagemanifests API is available. That way, we can check to see if the
// package is actually available to the cluster before creating the Operator
// package is actually available to the cluster before creating the Extension
// object.

opKey := types.NamespacedName{Name: i.Package}
Expand All @@ -51,9 +51,9 @@ func (i *OperatorInstall) Run(ctx context.Context) (*olmv1.ClusterExtension, err
return nil, err
}

// TODO(developer): Improve the logic in this poll wait once the Operator reconciler
// TODO(developer): Improve the logic in this poll wait once the Extension reconciler
// and conditions types and reasons are improved. For now, this will stop waiting as
// soon as a Ready condition is found, but we should probably wait until the Operator
// soon as a Ready condition is found, but we should probably wait until the Extension
// stops progressing.
// All Types will exist, so Ready may have a false Status. So, wait until
// Type=Ready,Status=True happens
Expand All @@ -68,7 +68,7 @@ func (i *OperatorInstall) Run(ctx context.Context) (*olmv1.ClusterExtension, err
}
return false, nil
}); err != nil {
return nil, fmt.Errorf("waiting for operator to become ready: %v", err)
return nil, fmt.Errorf("waiting for extension to become ready: %v", err)
}

return op, nil
Expand Down
Loading