You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2020/02/12 09:48:57 UTC
[camel-k] 02/06: Fix #1223: install and uninstall via OLM
This is an automated email from the ASF dual-hosted git repository.
astefanutti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 8228f4b84b510b224d4b3504eec4e6a2b08b586a
Author: Nicola Ferraro <ni...@gmail.com>
AuthorDate: Mon Feb 10 17:15:26 2020 +0100
Fix #1223: install and uninstall via OLM
---
pkg/apis/addtoscheme_olm.go | 2 ++
pkg/cmd/install.go | 16 +++++++----
pkg/cmd/uninstall.go | 64 ++++++++++++++++++++++++++++++-----------
pkg/util/olm/available.go | 6 +++-
pkg/util/olm/operator.go | 69 +++++++++++++++++++++++++++++++++++++--------
5 files changed, 121 insertions(+), 36 deletions(-)
diff --git a/pkg/apis/addtoscheme_olm.go b/pkg/apis/addtoscheme_olm.go
index a69aa84..d891e98 100644
--- a/pkg/apis/addtoscheme_olm.go
+++ b/pkg/apis/addtoscheme_olm.go
@@ -18,10 +18,12 @@ limitations under the License.
package apis
import (
+ olmv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
olmv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
)
func init() {
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
AddToSchemes = append(AddToSchemes, olmv1alpha1.AddToScheme)
+ AddToSchemes = append(AddToSchemes, olmv1.AddToScheme)
}
diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go
index 8e9c669..292c9d9 100644
--- a/pkg/cmd/install.go
+++ b/pkg/cmd/install.go
@@ -134,7 +134,7 @@ type installCmdOptions struct {
Global bool `mapstructure:"global"`
KanikoBuildCache bool `mapstructure:"kaniko-build-cache"`
Save bool `mapstructure:"save"`
- Olm bool `mapstructure:"olm"`
+ Olm bool `mapstructure:"olm"`
ClusterType string `mapstructure:"cluster-type"`
OutputFormat string `mapstructure:"output"`
RuntimeVersion string `mapstructure:"runtime-version"`
@@ -172,18 +172,22 @@ func (o *installCmdOptions) install(cobraCmd *cobra.Command, _ []string) error {
if olmClient, err = clientProvider.Get(); err != nil {
return err
}
- if installViaOLM, err = olm.IsAvailable(o.Context, olmClient); err != nil {
+ if installViaOLM, err = olm.IsAvailable(o.Context, olmClient, o.Namespace); err != nil {
return errors.Wrap(err, "error while checking OLM availability. Run with '--olm=false' to skip this check")
}
if installViaOLM {
- fmt.Fprintln(cobraCmd.OutOrStdout(), "OLM is available in the cluster");
- if err = olm.Install(o.Context, olmClient, o.Namespace, o.Global, o.olmOptions, collection); err != nil {
+ fmt.Fprintln(cobraCmd.OutOrStdout(), "OLM is available in the cluster")
+ var installed bool
+ if installed, err = olm.Install(o.Context, olmClient, o.Namespace, o.Global, o.olmOptions, collection); err != nil {
return err
}
+ if !installed {
+ fmt.Fprintln(cobraCmd.OutOrStdout(), "OLM resources are already available: skipping installation")
+ }
}
- if err = install.WaitForAllCRDInstallation(o.Context, clientProvider, 90 * time.Second); err != nil {
+ if err = install.WaitForAllCRDInstallation(o.Context, clientProvider, 90*time.Second); err != nil {
return err
}
}
@@ -202,7 +206,7 @@ func (o *installCmdOptions) install(cobraCmd *cobra.Command, _ []string) error {
if o.ClusterSetupOnly {
if collection == nil {
- fmt.Fprintln(cobraCmd.OutOrStdout(),"Camel K cluster setup completed successfully")
+ fmt.Fprintln(cobraCmd.OutOrStdout(), "Camel K cluster setup completed successfully")
}
} else {
c, err := o.GetCmdClient()
diff --git a/pkg/cmd/uninstall.go b/pkg/cmd/uninstall.go
index 045b1b8..11462f8 100644
--- a/pkg/cmd/uninstall.go
+++ b/pkg/cmd/uninstall.go
@@ -18,9 +18,10 @@ limitations under the License.
package cmd
import (
- "errors"
"fmt"
+ "github.com/apache/camel-k/pkg/util/olm"
+ "github.com/pkg/errors"
"k8s.io/client-go/kubernetes"
"github.com/apache/camel-k/pkg/client"
@@ -39,7 +40,7 @@ func newCmdUninstall(rootCmdOptions *RootCmdOptions) (*cobra.Command, *uninstall
Use: "uninstall",
Short: "Uninstall Camel K from a Kubernetes cluster",
Long: `Uninstalls Camel K from a Kubernetes or OpenShift cluster.`,
- Run: options.uninstall,
+ RunE: options.uninstall,
}
cmd.Flags().BoolVar(&options.skipOperator, "skip-operator", false, "Do not uninstall the Camel-K Operator in the current namespace")
@@ -50,6 +51,11 @@ func newCmdUninstall(rootCmdOptions *RootCmdOptions) (*cobra.Command, *uninstall
cmd.Flags().BoolVar(&options.skipIntegrationPlatform, "skip-integration-platform", false, "Do not uninstall the Camel-K Integration Platform in the current namespace")
cmd.Flags().BoolVar(&options.skipServiceAccounts, "skip-service-accounts", false, "Do not uninstall the Camel-K Service Accounts in the current namespace")
cmd.Flags().BoolVar(&options.skipConfigMaps, "skip-config-maps", false, "Do not uninstall the Camel-K Config Maps in the current namespace")
+ cmd.Flags().BoolVar(&options.global, "global", false, "Indicates that a global installation is going to be uninstalled (affects OLM)")
+ cmd.Flags().BoolVar(&options.olmEnabled, "olm", true, "Try to uninstall via OLM (Operator Lifecycle Manager) if available")
+ cmd.Flags().StringVar(&options.olmOptions.OperatorName, "olm-operator-name", olm.DefaultOperatorName, "Name of the Camel K operator in the OLM source or marketplace")
+ cmd.Flags().StringVar(&options.olmOptions.Package, "olm-package", olm.DefaultPackage, "Name of the Camel K package in the OLM source or marketplace")
+ cmd.Flags().StringVar(&options.olmOptions.GlobalNamespace, "olm-global-namespace", olm.DefaultGlobalNamespace, "A namespace containing an OperatorGroup that defines global scope for the operator (used in combination with the --global flag)")
// completion support
configureBashAnnotationForFlag(
@@ -73,6 +79,10 @@ type uninstallCmdOptions struct {
skipIntegrationPlatform bool
skipServiceAccounts bool
skipConfigMaps bool
+ olmEnabled bool
+ global bool
+
+ olmOptions olm.Options
}
var defaultListOptions = metav1.ListOptions{
@@ -80,33 +90,53 @@ var defaultListOptions = metav1.ListOptions{
}
// nolint: gocyclo
-func (o *uninstallCmdOptions) uninstall(_ *cobra.Command, _ []string) {
+func (o *uninstallCmdOptions) uninstall(cmd *cobra.Command, _ []string) error {
c, err := o.GetCmdClient()
if err != nil {
- return
+ return err
+ }
+
+ uninstallViaOLM := false
+ if o.olmEnabled {
+ var err error
+ if uninstallViaOLM, err = olm.IsAvailable(o.Context, c, o.Namespace); err != nil {
+ return errors.Wrap(err, "error while checking OLM availability. Run with '--olm=false' to skip this check")
+ }
+
+ if uninstallViaOLM {
+ fmt.Fprintln(cmd.OutOrStdout(), "OLM is available in the cluster")
+ if err = olm.Uninstall(o.Context, c, o.Namespace, o.global, o.olmOptions); err != nil {
+ return err
+ }
+ where := fmt.Sprintf("from namespace %s", o.Namespace)
+ if o.global {
+ where = "globally"
+ }
+ fmt.Fprintf(cmd.OutOrStdout(), "Camel-K OLM service removed %s\n", where)
+ }
}
if !o.skipIntegrationPlatform {
if err = o.uninstallIntegrationPlatform(); err != nil {
- fmt.Print(err)
- return
+ return err
}
- fmt.Printf("Camel-K Integration Platform removed from namespace %s\n", o.Namespace)
+ fmt.Fprintf(cmd.OutOrStdout(), "Camel-K Integration Platform removed from namespace %s\n", o.Namespace)
}
- if err = o.uninstallClusterWideResources(c); err != nil {
- fmt.Print(err)
- return
- }
- fmt.Printf("Camel-K Cluster Wide Resources removed from namespace %s\n", o.Namespace)
+ if !uninstallViaOLM {
+ if err = o.uninstallClusterWideResources(c); err != nil {
+ return err
+ }
+ fmt.Fprintf(cmd.OutOrStdout(), "Camel-K Cluster Wide Resources removed from namespace %s\n", o.Namespace)
- if !o.skipOperator {
- if err = o.uninstallOperator(c); err != nil {
- fmt.Print(err)
- return
+ if !o.skipOperator {
+ if err = o.uninstallOperator(c); err != nil {
+ return err
+ }
+ fmt.Fprintf(cmd.OutOrStdout(), "Camel-K Operator removed from namespace %s\n", o.Namespace)
}
- fmt.Printf("Camel-K Operator removed from namespace %s\n", o.Namespace)
}
+ return nil
}
func (o *uninstallCmdOptions) uninstallOperator(c client.Client) error {
diff --git a/pkg/util/olm/available.go b/pkg/util/olm/available.go
index 2d7636f..3c1d627 100644
--- a/pkg/util/olm/available.go
+++ b/pkg/util/olm/available.go
@@ -20,7 +20,9 @@ package olm
import (
"context"
+ "github.com/apache/camel-k/pkg/client"
kubernetesutils "github.com/apache/camel-k/pkg/util/kubernetes"
+ olmv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
olmv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -30,7 +32,7 @@ import (
// IsAvailable returns true if we are connected to a cluster with OLM installed
//
// This method should not be called from the operator, as it might require permissions that are not available.
-func IsAvailable(ctx context.Context, c kubernetes.Interface) (bool, error) {
+func IsAvailable(ctx context.Context, c client.Client, namespace string) (bool, error) {
// check some Knative APIs
for _, api := range getOLMGroupVersions() {
if installed, err := isAvailable(c, api); err != nil {
@@ -39,6 +41,7 @@ func IsAvailable(ctx context.Context, c kubernetes.Interface) (bool, error) {
return true, nil
}
}
+
return false, nil
}
@@ -55,5 +58,6 @@ func isAvailable(c kubernetes.Interface, api schema.GroupVersion) (bool, error)
func getOLMGroupVersions() []schema.GroupVersion {
return []schema.GroupVersion{
olmv1alpha1.SchemeGroupVersion,
+ olmv1.SchemeGroupVersion,
}
}
diff --git a/pkg/util/olm/operator.go b/pkg/util/olm/operator.go
index c5bda90..5b23d14 100644
--- a/pkg/util/olm/operator.go
+++ b/pkg/util/olm/operator.go
@@ -19,11 +19,14 @@ package olm
import (
"context"
+ "fmt"
"strings"
"github.com/apache/camel-k/pkg/client"
"github.com/apache/camel-k/pkg/util/kubernetes"
+ olmv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
olmv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
+ "github.com/pkg/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "sigs.k8s.io/controller-runtime/pkg/client"
)
@@ -54,13 +57,13 @@ var DefaultGlobalNamespace = "openshift-operators"
// Options contains information about an operator in OLM
type Options struct {
- OperatorName string
- Package string
- Channel string
- Source string
- SourceNamespace string
- StartingCSV string
- GlobalNamespace string
+ OperatorName string
+ Package string
+ Channel string
+ Source string
+ SourceNamespace string
+ StartingCSV string
+ GlobalNamespace string
}
// IsOperatorInstalled tells if a OLM CSV or a Subscription is already installed in the namespace
@@ -83,13 +86,13 @@ func IsOperatorInstalled(ctx context.Context, client client.Client, namespace st
}
// Install creates a subscription for the OLM package
-func Install(ctx context.Context, client client.Client, namespace string, global bool, options Options, collection *kubernetes.Collection) error {
+func Install(ctx context.Context, client client.Client, namespace string, global bool, options Options, collection *kubernetes.Collection) (bool, error) {
options = fillDefaults(options)
if installed, err := IsOperatorInstalled(ctx, client, namespace, global, options); err != nil {
- return err
+ return false, err
} else if installed {
// Already installed
- return nil
+ return false, nil
}
targetNamespace := namespace
@@ -113,9 +116,38 @@ func Install(ctx context.Context, client client.Client, namespace string, global
}
if collection != nil {
collection.Add(&sub)
- return nil
+ } else {
+ if err := client.Create(ctx, &sub); err != nil {
+ return false, err
+ }
+ }
+
+ if !global {
+ group, err := findOperatorGroup(ctx, client, namespace, options)
+ if err != nil {
+ return false, err
+ }
+ if group == nil {
+ group = &olmv1.OperatorGroup{
+ ObjectMeta: v1.ObjectMeta{
+ Namespace: namespace,
+ GenerateName: fmt.Sprintf("%s-", namespace),
+ },
+ Spec: olmv1.OperatorGroupSpec{
+ TargetNamespaces: []string{namespace},
+ },
+ }
+ if collection != nil {
+ collection.Add(group)
+ } else {
+ if err := client.Create(ctx, group); err != nil {
+ return false, errors.Wrap(err, fmt.Sprintf("namespace %s has no operator group defined and current user is not able to create it. " +
+ "Make sure you have the right roles to install operators from OLM", namespace))
+ }
+ }
+ }
}
- return client.Create(ctx, &sub)
+ return true, nil
}
// Uninstall removes CSV and subscription from the namespace
@@ -175,6 +207,19 @@ func findCSV(ctx context.Context, client client.Client, namespace string, option
return nil, nil
}
+func findOperatorGroup(ctx context.Context, client client.Client, namespace string, options Options) (*olmv1.OperatorGroup, error) {
+ opGroupList := olmv1.OperatorGroupList{}
+ if err := client.List(ctx, &opGroupList, runtime.InNamespace(namespace)); err != nil {
+ return nil, err
+ }
+
+ if len(opGroupList.Items) > 0 {
+ return &opGroupList.Items[0], nil
+ }
+
+ return nil, nil
+}
+
func fillDefaults(o Options) Options {
if o.OperatorName == "" {
o.OperatorName = DefaultOperatorName