Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add experimental OLMv1 support behind envvar toggle #84

Closed
Closed
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
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ go 1.19
require (
github.com/containerd/containerd v1.6.10
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.20.1
github.com/onsi/gomega v1.22.1
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
github.com/operator-framework/api v0.17.3
github.com/operator-framework/operator-controller v0.0.0-20230117211241-081c4b017b63
github.com/operator-framework/operator-lifecycle-manager v0.23.1
github.com/operator-framework/operator-registry v1.17.5
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
github.com/spf13/cobra v1.5.0
github.com/spf13/pflag v1.0.5
k8s.io/api v0.25.4
k8s.io/apiextensions-apiserver v0.25.4
Expand Down
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
Expand Down Expand Up @@ -804,7 +804,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
github.com/onsi/ginkgo/v2 v2.3.1 h1:8SbseP7qM32WcvE6VaN6vfXxv698izmsJ1UQX9ve7T8=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
Expand All @@ -816,8 +816,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI=
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
Expand Down Expand Up @@ -850,6 +850,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
github.com/operator-framework/api v0.7.1/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY=
github.com/operator-framework/api v0.17.3 h1:wddE1SLKTNiIzwt28DbBIO+vPG2GOV6dkB9xBkDfT3o=
github.com/operator-framework/api v0.17.3/go.mod h1:34tb98EwTN5SZLkgoxwvRkhMJKLHUWHOrrcv1ZwvEeA=
github.com/operator-framework/operator-controller v0.0.0-20230117211241-081c4b017b63 h1:WbLynlU3tCtiiRZA9S+k8qvkHvSlMWfqeA9Q9/PWK88=
github.com/operator-framework/operator-controller v0.0.0-20230117211241-081c4b017b63/go.mod h1:fxBWcATKNalFgRs89Hhyoo0gUydqW3A0jnYlGkKsAxU=
github.com/operator-framework/operator-lifecycle-manager v0.23.1 h1:Xw2ml1T4W2ieoFaVwanW/eFlZ11yAOJZUpUI8RLSql8=
github.com/operator-framework/operator-lifecycle-manager v0.23.1/go.mod h1:q/QgVi/WooEyOFw8ipQrb2A/InjM4djCwPf7IlCpSOQ=
github.com/operator-framework/operator-registry v1.17.5 h1:LR8m1rFz5Gcyje8WK6iYt+gIhtzqo52zMRALdmTYHT0=
Expand Down Expand Up @@ -957,8 +959,8 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
Expand Down
30 changes: 30 additions & 0 deletions internal/cmd/internal/olmv1/operator_install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package olmv1

import (
"github.com/spf13/cobra"

"github.com/operator-framework/kubectl-operator/internal/cmd/internal/log"
experimentalaction "github.com/operator-framework/kubectl-operator/internal/pkg/experimental/action"
"github.com/operator-framework/kubectl-operator/pkg/action"
)

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

cmd := &cobra.Command{
Use: "install <operator>",
Short: "Install an operator",
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.Printf("operator %q created", i.Package)
},
}

return cmd
}
34 changes: 34 additions & 0 deletions internal/cmd/internal/olmv1/operator_uninstall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package olmv1

import (
"github.com/spf13/cobra"

"github.com/operator-framework/kubectl-operator/internal/cmd/internal/log"
experimentalaction "github.com/operator-framework/kubectl-operator/internal/pkg/experimental/action"
"github.com/operator-framework/kubectl-operator/pkg/action"
)

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

cmd := &cobra.Command{
Use: "uninstall <operator>",
Short: "Uninstall an operator",
Long: `Uninstall deletes the named Operator object.

Warning: this command permanently deletes objects from the cluster. If the
uninstalled Operator bundle contains CRDs, the CRDs will be deleted, which
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.Printf("deleted operator %q", u.Package)
},
}
return cmd
}
39 changes: 22 additions & 17 deletions internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package cmd

import (
"context"
"reflect"
"fmt"
"os"
"time"
"unsafe"

"github.com/spf13/cobra"

"github.com/operator-framework/kubectl-operator/internal/cmd/internal/log"
"github.com/operator-framework/kubectl-operator/internal/cmd/internal/olmv1"
"github.com/operator-framework/kubectl-operator/pkg/action"
)

Expand All @@ -17,16 +18,24 @@ func Execute() {
log.Fatal(err)
}
}

const (
experimentalOLMV1EnvVar = "EXPERIMENTAL_USE_OLMV1_APIS"
)

func newCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "operator",
Short: "Manage operators in a cluster from the command line",
Long: `Manage operators in a cluster from the command line.
Long: fmt.Sprintf(`Manage operators in a cluster from the command line.

kubectl operator helps you manage operator installations in your
cluster. It can install and uninstall operator catalogs, list
operators available for installation, and install and uninstall
operators from the installed catalogs.`,
operators from the installed catalogs.

To try out experimental OLMv1 APIs, set "%s=on".
`, experimentalOLMV1EnvVar),
}

var (
Expand All @@ -42,18 +51,21 @@ operators from the installed catalogs.`,
cmd.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
var ctx context.Context
ctx, cancel = context.WithTimeout(cmd.Context(), timeout)

// This sets the unexported cmd.ctx value using unsafe. If
// https://github.com/spf13/cobra/pull/1118 gets merged, we
// should use cmd.SetContext() instead.
setContext(cmd, ctx)

cmd.SetContext(ctx)
return cfg.Load()
}
cmd.PersistentPostRun = func(command *cobra.Command, _ []string) {
cancel()
}

if v := os.Getenv(experimentalOLMV1EnvVar); v == "on" {
cmd.AddCommand(
olmv1.NewOperatorInstallCmd(&cfg),
olmv1.NewOperatorUninstallCmd(&cfg),
)
return cmd
}

cmd.AddCommand(
newCatalogCmd(&cfg),
newOperatorInstallCmd(&cfg),
Expand All @@ -68,10 +80,3 @@ operators from the installed catalogs.`,

return cmd
}

func setContext(cmd *cobra.Command, ctx context.Context) { //nolint:golint
rs := reflect.ValueOf(cmd).Elem()
rf := rs.FieldByName("ctx")
rf = reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem()
rf.Set(reflect.ValueOf(ctx))
}
67 changes: 67 additions & 0 deletions internal/pkg/experimental/action/operator_install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package action

import (
"context"
"fmt"
"time"

olmv1 "github.com/operator-framework/operator-controller/api/v1alpha1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"

"github.com/operator-framework/kubectl-operator/pkg/action"
)

type OperatorInstall struct {
config *action.Configuration

Package string

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

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

func (i *OperatorInstall) Run(ctx context.Context) (*olmv1.Operator, 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
// object.

opKey := types.NamespacedName{Name: i.Package}
op := &olmv1.Operator{
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
Spec: olmv1.OperatorSpec{PackageName: i.Package},
}
if err := i.config.Client.Create(ctx, op); err != nil {
return nil, err
}

// TODO(developer): Improve the logic in this poll wait once the Operator 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
// stops progressing.

if err := wait.PollImmediateUntil(time.Millisecond*250, func() (bool, error) {
if err := i.config.Client.Get(ctx, opKey, op); err != nil {
return false, err
}
readyCondition := meta.FindStatusCondition(op.Status.Conditions, olmv1.TypeReady)
if readyCondition == nil {
return false, nil
}
return true, nil
}, ctx.Done()); err != nil {
return nil, fmt.Errorf("waiting for operator to become ready: %v", err)
}

return op, nil
}
70 changes: 70 additions & 0 deletions internal/pkg/experimental/action/operator_uninstall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package action

import (
"context"
"fmt"
"strings"
"time"

olmv1 "github.com/operator-framework/operator-controller/api/v1alpha1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/operator-framework/kubectl-operator/pkg/action"
)

type OperatorUninstall struct {
config *action.Configuration

Package string

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

func NewOperatorUninstall(cfg *action.Configuration) *OperatorUninstall {
return &OperatorUninstall{
config: cfg,
Logf: func(string, ...interface{}) {},
}
}

func (u *OperatorUninstall) Run(ctx context.Context) error {
opKey := types.NamespacedName{Name: u.Package}
op := &olmv1.Operator{}
op.SetName(opKey.Name)
op.SetGroupVersionKind(olmv1.GroupVersion.WithKind("Operator"))

lowerKind := strings.ToLower(op.GetObjectKind().GroupVersionKind().Kind)
if err := u.config.Client.Delete(ctx, op); err != nil && !apierrors.IsNotFound(err) {
return fmt.Errorf("delete %s %q: %v", lowerKind, op.GetName(), err)
}
return waitForDeletion(ctx, u.config.Client, op)
}

func objectKeyForObject(obj client.Object) types.NamespacedName {
return types.NamespacedName{
Namespace: obj.GetNamespace(),
Name: obj.GetName(),
}
}

func waitForDeletion(ctx context.Context, cl client.Client, objs ...client.Object) error {
for _, obj := range objs {
obj := obj
lowerKind := strings.ToLower(obj.GetObjectKind().GroupVersionKind().Kind)
key := objectKeyForObject(obj)
if err := wait.PollImmediateUntil(250*time.Millisecond, func() (bool, error) {
if err := cl.Get(ctx, key, obj); apierrors.IsNotFound(err) {
return true, nil
} else if err != nil {
return false, err
}
return false, nil
}, ctx.Done()); err != nil {
return fmt.Errorf("wait for %s %q deleted: %v", lowerKind, key.Name, err)
}
}
return nil
}
2 changes: 2 additions & 0 deletions pkg/action/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

v1 "github.com/operator-framework/api/pkg/operators/v1"
"github.com/operator-framework/api/pkg/operators/v1alpha1"
olmv1 "github.com/operator-framework/operator-controller/api/v1alpha1"
operatorsv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1"
"github.com/spf13/pflag"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
Expand All @@ -20,6 +21,7 @@ func NewScheme() (*runtime.Scheme, error) {
operatorsv1.AddToScheme,
v1.AddToScheme,
apiextv1.AddToScheme,
olmv1.AddToScheme,
} {
if err := f(sch); err != nil {
return nil, err
Expand Down