This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch alignment-camel-main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 1996c52c5ed5dd98243856aed451777892cc5f39 Author: Tadayoshi Sato <[email protected]> AuthorDate: Thu Jun 3 17:36:56 2021 +0900 feat(cli): add sub command kamel kamelet for get and delete #2312 --- pkg/apis/camel/v1alpha1/kamelet_types.go | 10 +- pkg/cmd/kamelet.go | 35 +++++++ pkg/cmd/{kit_delete.go => kamelet_delete.go} | 101 +++++++++---------- pkg/cmd/kamelet_get.go | 139 +++++++++++++++++++++++++++ pkg/cmd/kit_delete.go | 2 +- pkg/cmd/root.go | 1 + pkg/install/kamelets.go | 6 +- 7 files changed, 234 insertions(+), 60 deletions(-) diff --git a/pkg/apis/camel/v1alpha1/kamelet_types.go b/pkg/apis/camel/v1alpha1/kamelet_types.go index fd10387..5a6def7 100644 --- a/pkg/apis/camel/v1alpha1/kamelet_types.go +++ b/pkg/apis/camel/v1alpha1/kamelet_types.go @@ -25,7 +25,15 @@ import ( ) const ( - AnnotationIcon = "camel.apache.org/kamelet.icon" + AnnotationIcon = "camel.apache.org/kamelet.icon" + KameletBundledLabel = "camel.apache.org/kamelet.bundled" + KameletReadOnlyLabel = "camel.apache.org/kamelet.readonly" + KameletTypeLabel = "camel.apache.org/kamelet.type" + KameletGroupLabel = "camel.apache.org/kamelet.group" + + KameletTypeSink = "sink" + KameletTypeSource = "source" + KameletTypeAction = "action" ) var ( diff --git a/pkg/cmd/kamelet.go b/pkg/cmd/kamelet.go new file mode 100644 index 0000000..89a0906 --- /dev/null +++ b/pkg/cmd/kamelet.go @@ -0,0 +1,35 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "github.com/spf13/cobra" +) + +func newCmdKamelet(rootCmdOptions *RootCmdOptions) *cobra.Command { + cmd := cobra.Command{ + Use: "kamelet", + Short: "Configure a Kamelet", + Long: `Configure a Kamelet.`, + } + + cmd.AddCommand(cmdOnly(newKameletGetCmd(rootCmdOptions))) + cmd.AddCommand(cmdOnly(newKameletDeleteCmd(rootCmdOptions))) + + return &cmd +} diff --git a/pkg/cmd/kit_delete.go b/pkg/cmd/kamelet_delete.go similarity index 50% copy from pkg/cmd/kit_delete.go copy to pkg/cmd/kamelet_delete.go index 53dec61..7f6ed67 100644 --- a/pkg/cmd/kit_delete.go +++ b/pkg/cmd/kamelet_delete.go @@ -21,25 +21,25 @@ import ( "errors" "fmt" - k8sclient "sigs.k8s.io/controller-runtime/pkg/client" - - v1 "github.com/apache/camel-k/pkg/apis/camel/v1" "github.com/spf13/cobra" - k8errors "k8s.io/apimachinery/pkg/api/errors" + + k8sclient "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" ) -func newKitDeleteCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *kitDeleteCommandOptions) { - options := kitDeleteCommandOptions{ +func newKameletDeleteCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *kameletDeleteCommandOptions) { + options := kameletDeleteCommandOptions{ RootCmdOptions: rootCmdOptions, } cmd := cobra.Command{ - Use: "delete", - Short: "Delete an Integration Kit", - Long: `Delete an Integration Kit.`, + Use: "delete <name>", + Short: "Delete a Kamelet", + Long: `Delete a Kamelet.`, PreRunE: decode(&options), - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { if err := options.validate(args); err != nil { return err } @@ -51,28 +51,28 @@ func newKitDeleteCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *kitDelete }, } - cmd.Flags().Bool("all", false, "Delete all integration Kits") + cmd.Flags().Bool("all", false, "Delete all Kamelets") return &cmd, &options } -type kitDeleteCommandOptions struct { +type kameletDeleteCommandOptions struct { *RootCmdOptions All bool `mapstructure:"all"` } -func (command *kitDeleteCommandOptions) validate(args []string) error { +func (command *kameletDeleteCommandOptions) validate(args []string) error { if command.All && len(args) > 0 { - return errors.New("invalid combination: both all flag and named Kits are set") + return errors.New("invalid combination: both all flag and named kamelets are set") } if !command.All && len(args) == 0 { - return errors.New("invalid combination: neither all flag nor named Kits are set") + return errors.New("invalid combination: neither all flag nor named kamelets are set") } return nil } -func (command *kitDeleteCommandOptions) run(args []string) error { +func (command *kameletDeleteCommandOptions) run(args []string) error { names := args c, err := command.GetCmdClient() @@ -81,16 +81,15 @@ func (command *kitDeleteCommandOptions) run(args []string) error { } if command.All { - kitList := v1.NewIntegrationKitList() - if err := c.List(command.Context, &kitList, k8sclient.InNamespace(command.Namespace)); err != nil { + klList := v1alpha1.NewKameletList() + if err := c.List(command.Context, &klList, k8sclient.InNamespace(command.Namespace)); err != nil { return err } - - names = make([]string, 0, len(kitList.Items)) - for _, item := range kitList.Items { - // only include non platform Kits - if item.Labels["camel.apache.org/kit.type"] != v1.IntegrationKitTypePlatform { - names = append(names, item.Name) + names = make([]string, 0, len(klList.Items)) + for _, kl := range klList.Items { + // only include non-bundled, non-readonly kamelets + if kl.Labels[v1alpha1.KameletBundledLabel] != "true" && kl.Labels[v1alpha1.KameletReadOnlyLabel] != "true" { + names = append(names, kl.Name) } } } @@ -104,50 +103,44 @@ func (command *kitDeleteCommandOptions) run(args []string) error { return nil } -func (command *kitDeleteCommandOptions) delete(name string) error { - ctx := v1.NewIntegrationKit(command.Namespace, name) - key := k8sclient.ObjectKey{ - Namespace: command.Namespace, - Name: name, - } +func (command *kameletDeleteCommandOptions) delete(name string) error { c, err := command.GetCmdClient() if err != nil { return err } - err = c.Get(command.Context, key, &ctx) - - // pass through if the kit is not found - if err != nil && k8errors.IsNotFound(err) { - return fmt.Errorf("no integration kit found with name \"%s\"", ctx.Name) + kl := v1alpha1.NewKamelet(command.Namespace, name) + key := k8sclient.ObjectKey{ + Namespace: command.Namespace, + Name: name, } - - // fail otherwise + err = c.Get(command.Context, key, &kl) if err != nil { - return err + if k8errors.IsNotFound(err) { + return fmt.Errorf("no kamelet found with name \"%s\"", name) + } else { + return err + } } - // check that it is not a platform one which is supposed to be "read only" + // check that it is not a bundled nor read-only one which is supposed to belong to platform // thus not managed by the end user - if ctx.Labels["camel.apache.org/kit.type"] == v1.IntegrationKitTypePlatform { - // skip platform Kits while deleting all Kits + if kl.Labels[v1alpha1.KameletBundledLabel] == "true" || kl.Labels[v1alpha1.KameletReadOnlyLabel] == "true" { + // skip platform Kamelets while deleting all Kamelets if command.All { return nil } - - return fmt.Errorf("integration kit \"%s\" is not editable", ctx.Name) + return fmt.Errorf("kamelet \"%s\" is not editable", name) } - err = c.Delete(command.Context, &ctx) - - if err != nil && !k8errors.IsNotFound(err) { - return fmt.Errorf("error deleting integration kit \"%s\", %s", ctx.Name, err) - } - if err != nil && k8errors.IsNotFound(err) { - return fmt.Errorf("no integration kit found with name \"%s\"", ctx.Name) + err = c.Delete(command.Context, &kl) + if err != nil { + if k8errors.IsNotFound(err) { + return fmt.Errorf("no kamelet found with name \"%s\"", name) + } else { + return fmt.Errorf("error deleting kamelet \"%s\", %s", name, err) + } } - - fmt.Printf("integration kit \"%s\" has been deleted\n", ctx.Name) - - return err + fmt.Printf("kamelet \"%s\" has been deleted\n", name) + return nil } diff --git a/pkg/cmd/kamelet_get.go b/pkg/cmd/kamelet_get.go new file mode 100644 index 0000000..b9e5cd4 --- /dev/null +++ b/pkg/cmd/kamelet_get.go @@ -0,0 +1,139 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "errors" + "fmt" + "strings" + "text/tabwriter" + + "github.com/spf13/cobra" + + k8sclient "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" +) + +func newKameletGetCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *kameletGetCommandOptions) { + options := kameletGetCommandOptions{ + RootCmdOptions: rootCmdOptions, + } + + cmd := cobra.Command{ + Use: "get", + Short: "Get defined Kamelet", + Long: `Get defined Kamelet.`, + PreRunE: decode(&options), + RunE: func(cmd *cobra.Command, args []string) error { + if err := options.validate(cmd, args); err != nil { + return err + } + if err := options.run(cmd); err != nil { + fmt.Println(err.Error()) + } + + return nil + }, + } + + cmd.Flags().Bool("sink", false, "Show only sink Kamelets") + cmd.Flags().Bool("source", false, "Show only source Kamelets") + cmd.Flags().Bool("action", false, "Show only action Kamelets") + cmd.Flags().String("group", "", "Filters Kamelets by group") + cmd.Flags().Bool("bundled", true, "Includes bundled Kamelets") + cmd.Flags().Bool("read-only", true, "Includes read-only Kamelets") + + return &cmd, &options +} + +type kameletGetCommandOptions struct { + *RootCmdOptions + Sink bool `mapstructure:"sink"` + Source bool `mapstructure:"source"` + Action bool `mapstructure:"action"` + Group string `mapstructure:"group"` + Bundled bool `mapstructure:"bundled"` + ReadOnly bool `mapstructure:"read-only"` +} + +func (command *kameletGetCommandOptions) validate(cmd *cobra.Command, args []string) error { + count := 0 + for _, b := range []bool{command.Sink, command.Source, command.Action} { + if b { + count++ + } + } + + if count > 1 { + return errors.New("invalid combination: flags --sink, --source, and --action are mutually exclusive") + } + return nil +} + +func (command *kameletGetCommandOptions) run(cmd *cobra.Command) error { + c, err := command.GetCmdClient() + if err != nil { + return err + } + + klList := v1alpha1.NewKameletList() + if err := c.List(command.Context, &klList, k8sclient.InNamespace(command.Namespace)); err != nil { + return err + } + + w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 8, 1, '\t', 0) + fmt.Fprintln(w, "NAME\tPHASE\tTYPE\tGROUP\tBUNDLED\tREAD ONLY\tTITLE") + for _, kl := range klList.Items { + klType := kl.Labels[v1alpha1.KameletTypeLabel] + group := kl.Annotations[v1alpha1.KameletGroupLabel] + bundled := kl.Labels[v1alpha1.KameletBundledLabel] + readOnly := kl.Labels[v1alpha1.KameletReadOnlyLabel] + + if command.Sink && klType != v1alpha1.KameletTypeSink { + continue + } + if command.Source && klType != v1alpha1.KameletTypeSource { + continue + } + if command.Action && klType != v1alpha1.KameletTypeAction { + continue + } + if command.Group != "" && !strings.EqualFold(command.Group, group) { + continue + } + if !command.Bundled && bundled == "true" { + continue + } + if !command.ReadOnly && readOnly == "true" { + continue + } + + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", + kl.Name, + string(kl.Status.Phase), + klType, + group, + bundled, + readOnly, + kl.Spec.Definition.Title) + } + w.Flush() + + return nil +} diff --git a/pkg/cmd/kit_delete.go b/pkg/cmd/kit_delete.go index 53dec61..0a0428d 100644 --- a/pkg/cmd/kit_delete.go +++ b/pkg/cmd/kit_delete.go @@ -35,7 +35,7 @@ func newKitDeleteCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *kitDelete } cmd := cobra.Command{ - Use: "delete", + Use: "delete <name>", Short: "Delete an Integration Kit", Long: `Delete an Integration Kit.`, PreRunE: decode(&options), diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index 0e2ff77..b982286 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -148,6 +148,7 @@ func addKamelSubcommands(cmd *cobra.Command, options *RootCmdOptions) { cmd.AddCommand(cmdOnly(newCmdDump(options))) cmd.AddCommand(newCmdLocal(options)) cmd.AddCommand(cmdOnly(newCmdBind(options))) + cmd.AddCommand(newCmdKamelet(options)) } func addHelpSubCommands(cmd *cobra.Command, options *RootCmdOptions) error { diff --git a/pkg/install/kamelets.go b/pkg/install/kamelets.go index 6d92b9d..939c6a9 100644 --- a/pkg/install/kamelets.go +++ b/pkg/install/kamelets.go @@ -37,8 +37,6 @@ import ( const kameletDirEnv = "KAMELET_CATALOG_DIR" const defaultKameletDir = "/kamelets/" -const kameletBundledLabel = "camel.apache.org/kamelet.bundled" -const kameletReadOnlyLabel = "camel.apache.org/kamelet.readonly" // KameletCatalog installs the bundled KameletCatalog into one namespace func KameletCatalog(ctx context.Context, c client.Client, namespace string) error { @@ -93,8 +91,8 @@ func KameletCatalog(ctx context.Context, c client.Client, namespace string) erro if k.GetLabels() == nil { k.SetLabels(make(map[string]string)) } - k.GetLabels()[kameletBundledLabel] = "true" - k.GetLabels()[kameletReadOnlyLabel] = "true" + k.GetLabels()[v1alpha1.KameletBundledLabel] = "true" + k.GetLabels()[v1alpha1.KameletReadOnlyLabel] = "true" err := ObjectOrCollect(ctx, c, namespace, nil, true, k)
